codeforces #600 (div 2) 做题记录

时间:2019-11-21
本文章向大家介绍codeforces #600 (div 2) 做题记录,主要包括codeforces #600 (div 2) 做题记录使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

A.

两个数组作差判一判就行了

 1 #include<bits/stdc++.h>
 2 #define maxn 100005
 3 using namespace std;
 4 int T,n;
 5 int a[maxn],b[maxn];
 6 int main()
 7 {
 8     scanf("%d",&T);
 9     while(T--)
10     {
11         scanf("%d",&n);
12         for(int i=1;i<=n;++i)scanf("%d",&a[i]);
13         for(int i=1;i<=n;++i)scanf("%d",&b[i]);
14         for(int i=1;i<=n;++i)a[i]-=b[i];
15         bool yes=1;
16         for(int i=1;i<=n;++i)if(a[i]>0)yes=0;
17         int cnt=0;
18         for(int i=1;i<=n;++i)
19         {
20             if(a[i]!=0&&a[i-1]==0)cnt++;
21             if(a[i]!=0&&a[i-1]!=0&&a[i]!=a[i-1])yes=0;
22         }
23         if(yes&&cnt<=1)puts("YES");
24         else puts("NO");
25     }
26 }
View Code

B.

用一个set维护已经出现的正的,一个set维护当天用过的(出现一正一负的)

然后各种边界判一判

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n;
 4 set<int> s,used;
 5 int main()
 6 {
 7     scanf("%d",&n);
 8     bool yes=1;
 9     vector<int> Ans;Ans.clear();
10     Ans.push_back(0);
11     for(int i=1;i<=n;++i)
12     {
13         int x;
14         scanf("%d",&x);
15         if(x<0)
16         {
17             if(!s.count(-x)){yes=0;break;}
18             s.erase(-x),used.insert(-x);
19         }
20         else
21         {
22             if(s.count(x)){yes=0;break;}
23             s.insert(x);
24         }
25         if(s.count(abs(x))&&used.count(abs(x)))yes=0;
26         if(s.empty())Ans.push_back(i),used.clear();
27     }
28     if(!s.empty())yes=0; 
29     if(!yes)
30     {
31         puts("-1");
32         return 0;
33     }
34     printf("%d\n",Ans.size()-1);
35     for(int i=1;i<Ans.size();++i)printf("%d ",Ans[i]-Ans[i-1]);
36 }
View Code

C.

考虑贪心,一定是从小朝大选

然后考虑把哪些放在靠前的天数,一定是较小的那些

然后在\( \bmod m\)意义下维护一下就行了

 1 #include<bits/stdc++.h>
 2 #define maxn 1000005
 3 #define ll long long
 4 using namespace std;
 5 int n,m;
 6 ll a[maxn],s[maxn];
 7 int main()
 8 {
 9     scanf("%d%d",&n,&m);
10     for(int i=1;i<=n;++i)scanf("%I64d",&a[i]);
11     sort(a+1,a+n+1);
12     ll ans=0;
13     for(int i=1;i<=n;++i)
14     {
15         ans+=s[i%m];
16         s[i%m]+=a[i];
17         ans+=a[i];
18         printf("%I64d ",ans);
19     }
20 }
View Code

D.

考虑一定是连续的一段编号连通

那么我们从左往右扫,并用一个并查集维护每个连通块里编号最大的点

然后剩下这段的点都接上去就行了

 1 #include<bits/stdc++.h>
 2 #define maxn 200005
 3 using namespace std;
 4 int n,m;
 5 int fa[maxn],sz[maxn],mx[maxn];
 6 int find(int x)
 7 {
 8     while(x!=fa[x])x=fa[x];
 9     return x;
10 }
11 void merge(int u,int v)
12 {
13     if(find(u)==find(v))return;
14     int fu=find(u),fv=find(v);
15     if(sz[fu]<sz[fv])fa[fu]=fv,mx[fv]=max(mx[fv],mx[fu]),sz[fv]+=sz[fu];
16     else fa[fv]=fu,mx[fu]=max(mx[fu],mx[fv]),sz[fu]+=sz[fv];
17 }
18 int main()
19 {
20     scanf("%d%d",&n,&m);
21     for(int i=1;i<=n;++i)fa[i]=i,sz[i]=1,mx[i]=i;
22     for(int i=1;i<=m;++i)
23     {
24         int u,v;
25         scanf("%d%d",&u,&v);
26         merge(u,v);
27     }
28     int ans=0;
29     for(int l=1;l<=n;++l)
30     {
31         for(int r=l+1;r<mx[find(l)];++r)
32         {
33             if(find(l)!=find(r))ans++,merge(l,r);
34         }
35         l=mx[find(l)];
36     }
37     cout<<ans<<endl;
38 }
View Code

E.

考虑DP

\(dp[i][j]\)表示第\(i\)个位置被\(j\)号区间覆盖

然后考虑转移:

1.延续这个区间:如果在这个区间内,那么直接延伸,否则用1费延伸

2.更新对称位置:这个点已经被覆盖了,那么到对称位置肯定也一直被覆盖,转移一下取个\(min\)

2.换一个区间:枚举另外一个区间,用另外一个区间,加上花费就行了

 1 #include<bits/stdc++.h>
 2 #define maxn 85
 3 #define maxm 100005
 4 using namespace std;
 5 int n,m;
 6 int X[maxn],S[maxn];
 7 int dp[maxm][maxn];
 8 int main()
 9 {
10     scanf("%d%d",&n,&m);
11     for(int i=1;i<=n;++i)scanf("%d%d",&X[i],&S[i]);
12     for(int i=1;i<=n;++i)dp[1][i]=max(0,X[i]-S[i]-1);
13     for(int i=2;i<=m;++i)
14         for(int j=1;j<=n;++j)dp[i][j]=1000000000;
15     for(int i=1;i<m;++i)
16     {
17         for(int j=1;j<=n;++j)
18         {
19             if(i+1<=X[j]+S[j])dp[i+1][j]=min(dp[i+1][j],dp[i][j]);
20             else dp[i+1][j]=min(dp[i+1][j],dp[i][j]+1);
21             if(i<=X[j])dp[min(2*X[j]-i,m)][j]=min(dp[min(2*X[j]-i,m)][j],dp[i][j]);
22             for(int k=1;k<=n;++k)if(k!=j&&i<=X[k])
23             {
24                 if(X[k]-S[k]<=i)dp[i+1][k]=min(dp[i+1][k],dp[i][j]);
25                 else dp[i+1][k]=min(dp[i+1][k],dp[i][j]+X[k]-S[k]-(i+1));
26             }
27         }
28     }
29     int ans=1000000000;
30     for(int i=1;i<=n;++i)ans=min(ans,dp[m][i]);
31     cout<<ans<<endl;
32 }
View Code

F.

原文地址:https://www.cnblogs.com/uuzlove/p/11907678.html