1. 程式人生 > >【Codeforces】Codeforces Round #551 (Div. 2) 解題報告

【Codeforces】Codeforces Round #551 (Div. 2) 解題報告

交點 span 兩個 read 得到 一次 pos hit preview

比賽鏈接

這一個月有點松弛了,吃了好多虧。這一個月來打的第一場CF就當成是停止放松的開始吧。

在寫A的時候用到了一個叫做fst的變量,於是...但是還是漲了一點點分(我上次是多慘啊)。

不敢tui不敢tui...自閉+自卑了。

A. Serval and Bus


題目大意:一個傻憨憨t時到車站,見車就坐,給出每輛公交車首班車到達時間及之後的時間間隔,求傻憨憨最後上的是哪一輛車。

數據範圍:1 ?? 100 , 1 ≤ n ≤ 100 , 1 ≤ t 105 , 1 ≤ si,di 105

無代碼

B. Serval and Toy Bricks

題目大意:有一堆積木,占了n×m的地方,告訴你從側視圖(正?),以及那些位置上有積木,求一種可行方案。

數據範圍:1??,??,?100

無代碼

C. Serval and Parenthesis Sequence

題目大意:有一個括號序列,要求它本身合法且它的所有前綴都嚴格不合法,現在有一些位置不確定,求一種合法方案,否則輸出 " :( " (我跟你講我現在就這個表情)

數據範圍:1 ≤ |s| 105

先判無解,再貪心,盡可能先放做括號 "(" 這樣前綴就不容易出現合法的,最後再判下合法就可以了。

無代碼

D. Serval and Rooted Tree

題目大意:給出一棵根節點是1的樹,現在需要在k個葉節點上放了1~k這些數作為權值,除葉節點外每個節點都會從其所有兒子裏取min or max權值,求根節點權值的最大值 數據範圍:2??3*105

對於min節點來說,如果有x個兒子,那麽就只能取到第x小的元素,取不到前dp[i]個。令dp[i]表示i的兒子中取不到前dp[i]個,min節點取它兒子dp的和,max節點取它兒子dp的最小值,答案為k-dp[1]+1

代碼:

技術分享圖片
 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4
#include<vector> 5 using namespace std; 6 7 template<class T>void read(T &x){ 8 x=0; bool f=0; char c=getchar(); 9 while(c<0||9<c){f|=(c==-); c=getchar();} 10 while(0<=c&&c<=9){x=(x<<1)+(x<<3)+(c^48); c=getchar();} 11 x=f?-x:x; 12 } 13 14 const int N=300050; 15 const int inf=N; 16 int n,k; 17 int a[N],fa[N],dp[N]; 18 vector<int>son[N]; 19 20 void dfs(int x){ 21 if(son[x].size()==0){dp[x]=1; ++k; return ;} 22 a[x]?dp[x]=inf:dp[x]=0; 23 for(int i=son[x].size()-1,y;~i;--i){ 24 y=son[x][i]; 25 dfs(y); 26 a[x]?dp[x]=min(dp[x],dp[y]):dp[x]+=dp[y]; 27 } 28 } 29 int main(){ 30 read(n); 31 for(int i=1;i<=n;++i)read(a[i]); 32 for(int i=2;i<=n;++i)read(fa[i]), son[fa[i]].push_back(i); 33 dfs(1); 34 printf("%d",k-dp[1]+1); 35 return 0; 36 }

E. Serval and Snake

數據範圍:
(交互! 貫徹了交互題都是水題但是像我這樣的傻憨憨不看的精神???)在一個n×n的網格裏有一條蛇,我們向交互庫查詢它的一個子網格,並且告訴你蛇的身體經過這個子網格邊界的次數(交點)。請在2019次查詢內找到蛇頭和蛇尾的位置(不需要區分頭尾)。

數據範圍:2??≤1000

仔細想想我們發現在一個網格圖中如果不包含蛇的頭或尾是蛇的身體的一部分,就是一進一出,一進一出,一進一出...交點個數是偶數。反之就必然有頭或尾在網格中。

我們先詢問所有行和列(2*n次詢問至多2000次),一定得到至少兩行或者兩列是奇數:頭和尾在這兩行或列中。

如果只有兩行或者兩列是奇數,那麽蛇頭蛇尾在同一行或者列中,用剩下的次數二分這行(列)的位置。

否則就是在不同的行列中,查詢一次就可以確定兩個點的位置。

代碼:

技術分享圖片
 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 using namespace std;
 5 
 6 inline int read(){
 7     int x=0; char c=getchar();
 8     while(c<0||9<c)c=getchar();
 9     while(0<=c&&c<=9){x=(x<<3)+(x<<1)+(c^48); c=getchar();}
10     return x;
11 }
12 
13 int n;
14 int h[3],p[3];
15 int a,b;
16 
17 int ask(int a,int b,int c,int d){
18     fflush(stdout);
19     printf("? %d %d %d %d\n",a,b,c,d);
20     fflush(stdout);
21     return read()&1;
22 }
23 
24 int main(){
25     n=read();
26     for(int i=1;i<=n;++i){
27         if(ask(i,1,i,n))h[++a]=i;
28         if(a>=2)break;
29     }
30     for(int i=1;i<=n;++i){
31         if(ask(1,i,n,i))p[++b]=i;
32         if(b>=2)break;
33     }
34     if(a&&b){
35         if(ask(h[1],p[1],h[1],p[1]))printf("! %d %d %d %d\n",h[1],p[1],h[2],p[2]);
36         else printf("! %d %d %d %d\n",h[1],p[2],h[2],p[1]);
37         return 0;
38     }
39     if(!a){
40         int l=1,r=n,mid,ans;
41         while(l<=r){
42             mid=(l+r)>>1;
43             if(ask(1,p[1],mid,p[1])){
44                 ans=mid;
45                 r=mid-1;
46             }
47             else l=mid+1;
48         }
49         printf("! %d %d %d %d\n",ans,p[1],ans,p[2]);
50         return 0;
51     }
52     if(!b){
53         int l=1,r=n,mid,ans;
54         while(l<=r){
55             mid=(l+r)>>1;
56             if(ask(h[1],1,h[1],mid)){
57                 ans=mid;
58                 r=mid-1;
59             }
60             else l=mid+1;
61         }
62         printf("! %d %d %d %d\n",h[1],ans,h[2],ans);
63         return 0;
64     }
65 }

F. Serval and Bonus Problem
題目大意:還沒看懂...
數據範圍:
科技點不足。坑待填。

【Codeforces】Codeforces Round #551 (Div. 2) 解題報告