• 【codeforces】【比赛题解】#920 Educational CF Round 37


    【A】浇花

    题意:

    一个线段上每个整点都有花,有的点有自动浇花的喷水器,有问几秒能浇完所有的花。

    题解:

    大模拟

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define F(i,a,b) for(int i=(a);i<=(b);++i)
     5 #define F2(i,a,b) for(int i=(a);i<(b);++i)
     6 #define dF(i,a,b) for(int i=(a);i>=(b);--i)
     7 #define dF2(i,a,b) for(int i=(a);i>(b);--i)
     8 #include<cmath>
     9 #include<iostream>
    10 #include<vector>
    11 #include<string>
    12 #include<queue>
    13 #include<set>
    14 #include<map>
    15 #define ll long long
    16 #define eF(i,u) for(int i=h[u];i;i=nxt[i])
    17 using namespace std;
    18 const int INF=0x3f3f3f3f;
    19 inline int Abs(int X){return X<0?-X:X;}
    20 inline int Gcd(int X,int Y){return Y?Gcd(Y,X%Y):X;}
    21 inline ll Gcd(ll X,ll Y){return Y?Gcd(Y,X%Y):X;}
    22 inline int Max(int X,int Y){return X<Y?Y:X;}
    23 inline int Min(int X,int Y){return X<Y?X:Y;}
    24 inline ll Max(ll X,ll Y){return X<Y?Y:X;}
    25 inline ll Min(ll X,ll Y){return X<Y?X:Y;}
    26 inline int Pow(int base,ll exp,int _mod){int _ans=1;for(;exp;exp>>=1,base=(ll)base*base%_mod)exp&1?_ans=(ll)_ans*base%_mod:0;return _ans;}
    27 inline ll Pow(ll base,ll exp,ll _mod){ll _ans=1;for(;exp;exp>>=1,base=base*base%_mod)exp&1?_ans=_ans*base%_mod:0;return _ans;}
    28 int n,q,Ans;
    29 int a[100001],b[100001];
    30 int main(){
    31     int T;
    32     scanf("%d",&T);
    33     while(T--){
    34         Ans=0;
    35         scanf("%d%d",&n,&q);
    36         F(i,1,q) scanf("%d",a+i);
    37         F(i,1,n){
    38             int k=999999999;
    39             F(j,1,q){
    40                 k=Min(k,Abs(i-a[j]));
    41             }
    42             Ans=Max(Ans,k);
    43         }
    44         printf("%d
    ",Ans+1);
    45     }
    46     return 0;
    47 }

    【B】排队喝茶

    题意:

    有(n)个人排队喝茶,第(i)个人(l_i)时刻来排队,如果(r_i)时刻还没有排到他,他就走了,问每个人喝到茶的时间或者他没有喝到茶。

    题解:

    大模拟,每个人是否走了可以到他了再判断。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define F(i,a,b) for(int i=(a);i<=(b);++i)
     5 #define F2(i,a,b) for(int i=(a);i<(b);++i)
     6 #define dF(i,a,b) for(int i=(a);i>=(b);--i)
     7 #define dF2(i,a,b) for(int i=(a);i>(b);--i)
     8 #include<cmath>
     9 #include<iostream>
    10 #include<vector>
    11 #include<string>
    12 #include<queue>
    13 #include<set>
    14 #include<map>
    15 #define ll long long
    16 #define eF(i,u) for(int i=h[u];i;i=nxt[i])
    17 using namespace std;
    18 const int INF=0x3f3f3f3f;
    19 inline int Gcd(int X,int Y){return Y?Gcd(Y,X%Y):X;}
    20 inline ll Gcd(ll X,ll Y){return Y?Gcd(Y,X%Y):X;}
    21 inline int Max(int X,int Y){return X<Y?Y:X;}
    22 inline int Min(int X,int Y){return X<Y?X:Y;}
    23 inline ll Max(ll X,ll Y){return X<Y?Y:X;}
    24 inline ll Min(ll X,ll Y){return X<Y?X:Y;}
    25 inline int Pow(int base,ll exp,int _mod){int _ans=1;for(;exp;exp>>=1,base=(ll)base*base%_mod)exp&1?_ans=(ll)_ans*base%_mod:0;return _ans;}
    26 inline ll Pow(ll base,ll exp,ll _mod){ll _ans=1;for(;exp;exp>>=1,base=base*base%_mod)exp&1?_ans=_ans*base%_mod:0;return _ans;}
    27 int n,q;
    28 int l[100001],r[100001],Ans[10001];
    29 int que[100001],L,R;
    30 int main(){
    31     int T;
    32     scanf("%d",&T);
    33     while(T--){
    34         L=1, R=0;
    35         scanf("%d",&n);
    36         memset(Ans,0,sizeof Ans);
    37         F(i,1,n) scanf("%d%d",l+i,r+i);
    38         int i=1;
    39         F(t,1,5000){
    40             while(l[i]==t) que[++R]=i, ++i;
    41             while(L<=R&&r[que[L]]<t) ++L;
    42             if(L<=R) Ans[que[L++]]=t;
    43         }
    44         F(j,1,n) printf("%d ",Ans[j]); puts("");
    45     }
    46     return 0;
    47 }

    【C】交换相邻元素

    题意:

    一个1到n的排列,你可以交换某些相邻位置的值,问能否交换成上升序列。

    题解:

    连续的一串可以交换的,就表示这一串可以直接排序,那么我们把所有连续的一段都各自排序,看最终的数组是否升序即可。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define F(i,a,b) for(int i=(a);i<=(b);++i)
     5 #define F2(i,a,b) for(int i=(a);i<(b);++i)
     6 #define dF(i,a,b) for(int i=(a);i>=(b);--i)
     7 #define dF2(i,a,b) for(int i=(a);i>(b);--i)
     8 #include<cmath>
     9 #include<iostream>
    10 #include<vector>
    11 #include<string>
    12 #include<queue>
    13 #include<set>
    14 #include<map>
    15 #define ll long long
    16 #define eF(i,u) for(int i=h[u];i;i=nxt[i])
    17 using namespace std;
    18 const int INF=0x3f3f3f3f;
    19 inline int Gcd(int X,int Y){return Y?Gcd(Y,X%Y):X;}
    20 inline ll Gcd(ll X,ll Y){return Y?Gcd(Y,X%Y):X;}
    21 inline int Max(int X,int Y){return X<Y?Y:X;}
    22 inline int Min(int X,int Y){return X<Y?X:Y;}
    23 inline ll Max(ll X,ll Y){return X<Y?Y:X;}
    24 inline ll Min(ll X,ll Y){return X<Y?X:Y;}
    25 inline int Pow(int base,ll exp,int _mod){int _ans=1;for(;exp;exp>>=1,base=(ll)base*base%_mod)exp&1?_ans=(ll)_ans*base%_mod:0;return _ans;}
    26 inline ll Pow(ll base,ll exp,ll _mod){ll _ans=1;for(;exp;exp>>=1,base=base*base%_mod)exp&1?_ans=_ans*base%_mod:0;return _ans;}
    27 int n,q;
    28 int a[200001],b[200001];
    29 int main(){
    30     scanf("%d",&n);
    31     F(i,1,n) scanf("%d",a+i);
    32     char ch;
    33     F2(i,1,n) if((ch=getchar())!='1'&&ch!='0') --i; else b[i]=ch-'0';
    34     int lst=1;
    35     F(i,1,n){
    36         if(!b[i]) sort(a+lst,a+i+1), lst=i+1;
    37     } sort(a+lst,a+n+1);
    38     F(i,1,n) if(a[i]!=i) {puts("NO"); return 0;}
    39     puts("YES");
    40     return 0;
    41 }

    【D】水缸

    题意:

    有一些容量无限的水缸,初始时每个水缸中各自有一些水,你有一个容积为k的勺子,问你能否通过用勺子舀水让一个水缸中的水变成要求的V体积?

    题解:

    考虑把所有的水缸的水和要求的V体积都对勺子容积k取模。

    那么如果有一些水缸中的水相加,再对k取模,等于V对k取模的结果,我们就确定最终的V体积的水来自这些水缸。

    那么用(f[i][j])表示前(i)个水缸中能否相加达到(j)容积((j)对(k)取模)。

    特别地,(f[i][j]=1)表示这一个水缸不需要选,(f[i][j]=2)表示这一个水缸可以选。

    那么最终确定结果时可以反推回来,确定选取哪些水缸。

    之后的事情主要是分类讨论,注意输出格式。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define F(i,a,b) for(int i=(a);i<=(b);++i)
     5 #define F2(i,a,b) for(int i=(a);i<(b);++i)
     6 #define dF(i,a,b) for(int i=(a);i>=(b);--i)
     7 #define dF2(i,a,b) for(int i=(a);i>(b);--i)
     8 #include<cmath>
     9 #include<iostream>
    10 #include<vector>
    11 #include<string>
    12 #include<queue>
    13 #include<set>
    14 #include<map>
    15 #define ll long long
    16 #define eF(i,u) for(int i=h[u];i;i=nxt[i])
    17 using namespace std;
    18 const int INF=0x3f3f3f3f;
    19 inline int Gcd(int X,int Y){return Y?Gcd(Y,X%Y):X;}
    20 inline ll Gcd(ll X,ll Y){return Y?Gcd(Y,X%Y):X;}
    21 inline int Max(int X,int Y){return X<Y?Y:X;}
    22 inline int Min(int X,int Y){return X<Y?X:Y;}
    23 inline ll Max(ll X,ll Y){return X<Y?Y:X;}
    24 inline ll Min(ll X,ll Y){return X<Y?X:Y;}
    25 inline int Pow(int base,ll exp,int _mod){int _ans=1;for(;exp;exp>>=1,base=(ll)base*base%_mod)exp&1?_ans=(ll)_ans*base%_mod:0;return _ans;}
    26 inline ll Pow(ll base,ll exp,ll _mod){ll _ans=1;for(;exp;exp>>=1,base=base*base%_mod)exp&1?_ans=_ans*base%_mod:0;return _ans;}
    27 int n,k,v;
    28 int a[5001],b[5001],sum,s2;
    29 int f[5001][5001];
    30 int Ans[5001];
    31 int main(){
    32     scanf("%d%d%d",&n,&k,&v);
    33     F(i,1,n) scanf("%d",a+i), sum+=a[i], b[i]=a[i], a[i]%=k;
    34 //    F(i,1,n) printf("%d ",a[i]); puts("");
    35     if(sum<v) {puts("NO"); return 0;}
    36     f[0][0]=1;
    37     F(i,1,n){
    38         F2(j,0,k){
    39             if(f[i-1][j]){
    40                 f[i][j]=1;
    41                 if(j+a[i]<k) f[i][j+a[i]]=2;
    42                 else f[i][j+a[i]-k]=2;
    43             }
    44         }
    45     }
    46 //    F(i,1,n){
    47 //        F2(j,0,k){
    48 //            printf("%d ",f[i][j]);
    49 //        }
    50 //        puts("");
    51 //    }
    52     if(f[n][v%k]==0) puts("NO");
    53     else{
    54         puts("YES");
    55         int now=v%k;
    56         int u=-1, unu=-1;
    57         dF(i,n,1){
    58             if(f[i][now]==2) Ans[i]=1, now=(now-a[i]+k)%k;
    59         }
    60 //        printf("ans:"); F(i,1,n) printf("%d ",Ans[i]); puts("");
    61         F(i,1,n) if(!Ans[i]) unu=i; else u=i;
    62 //        printf("u : %d, unu : %d
    ",u,unu);
    63         if(u==-1){
    64             F(i,2,n) if(b[i]>0) printf("%d %d 1
    ",(b[i]-1)/k+1,i);
    65             if(v>0) printf("%d 1 2
    ",v/k);
    66         }
    67         else if(unu==-1){
    68             F(i,2,n) if(b[i]>0) printf("%d %d 1
    ",(b[i]-1)/k+1,i);
    69             if(sum-v>0) printf("%d 1 2
    ",(sum-v)/k);
    70         }
    71         else{
    72             int s1=b[u],s2=b[unu];
    73             F(i,1,n){
    74                 if(Ans[i]==1&&i!=u&&b[i]>0) printf("%d %d %d
    ",(b[i]-1)/k+1,i,u), s1+=b[i];
    75                 if(Ans[i]==0&&i!=unu&&b[i]>0) printf("%d %d %d
    ",(b[i]-1)/k+1,i,unu), s2+=b[i];
    76             }
    77             if(s2>=k) printf("%d %d %d
    ",s2/k,unu,u); s1+=s2/k*k;
    78             if(s1-v>=k) printf("%d %d %d
    ",(s1-v)/k,u,unu);
    79         }
    80     }
    81     return 0;
    82 }

     【E】连通分量?

    题意:

    从一个(n)个点的无向完全图中删去(m)条边,问现在图中连通分量个数和每个连通分量大小。

    题解:

    看了别人的博才发现这题其实非常简单暴力。

    就是暴力BFS,不过下一个点要从还没到过的点的集合中枚举,就这么简单。

    为什么不会TLE?我们算一下时间复杂度:

    每个点都只会经过一次,也只会遍历一次。那么遍历当前点时,要花多少时间呢?

    在剩下的点中枚举,就是枚举到没有删除的边就会把这个点加入队列吧,每个点只要加入了队列它就不会被再搜到,所以枚举点的复杂度是(O(log;n))的,因为我使用了STL的set容器。

    但是如果搜到了被删除的边呢?这样的边可以保证只会被搜到最多2m次,从一条边的两端点出发。

    那么最终复杂度是(O(n(log;n+log;m))),非常巧妙。

    #include<cstdio>
    #define F(i,a,b) for(int i=(a);i<=(b);++i)
    #include<set>
    using namespace std;
    inline int Max(int X,int Y){return X<Y?Y:X;}
    inline int Min(int X,int Y){return X<Y?X:Y;}
    int n,m;
    set<int> vv;
    set<pair<int,int> > st;
    bool vis[200001];
    int que[200001],l,r;
    int Ans[200001],ans;
    int main(){
    	scanf("%d%d",&n,&m);
    	int x,y; F(i,1,m) scanf("%d%d",&x,&y), st.insert(make_pair(Min(x,y),Max(x,y)));
    	F(i,1,n) vv.insert(i);
    	F(i,1,n){
    		if(!vis[i]){
    			vis[i]=1; vv.erase(i);
    			que[l=r=1]=i;
    			while(l<=r){
    				int u=que[l++];
    				for(set<int>::iterator j=vv.begin();j!=vv.end();){
    					if(!st.count(make_pair(Min(u,*j),Max(u,*j))))
    						que[++r]=*j, vis[*j]=1, vv.erase(j++);
    					else ++j;
    				}
    			}
    			++Ans[r]; ++ans;
    		}
    	}
    	printf("%d
    ",ans);
    	F(i,1,n) while(Ans[i]--) printf("%d ",i);
    	return 0;
    }
    
  • 相关阅读:
    洛谷P3513 [POI2011]KON-Conspiracy
    柱状图 三分法+树状数组
    CF习题集三
    CF习题集二
    CF习题集一
    单调队列总结
    SP688 SAM
    lemon使用方法
    洛谷 P2403 [SDOI2010]所驼门王的宝藏 题解
    字符串学习笔记二
  • 原文地址:https://www.cnblogs.com/PinkRabbit/p/8410711.html
Copyright © 2020-2023  润新知