Codeforces Round #540 (Div. 3)

A、题目意思理解就过了

B、读了题目没有写,但是依稀感觉是前缀和,不过写残了。题解代码非常简洁。

维护前缀、后缀奇数和,维护前缀、后缀偶数和。

题解把遍历过的数都减去了,也就维护了后缀和。

前缀过一个加一个。

 1 #include<bits/stdc++.h>
 2 typedef long long ll;
 3 int a[200010];
 4 
 5 int main() {
 6     int n,Osum=0,Esum=0,Oper=0,Eper=0;
 7     scanf("%d",&n);
 8     for(int i=0;i<n;i++) {
 9         scanf("%d",&a[i]);
10         if(i&1) Esum+=a[i];
11         else Osum+=a[i];
12     }
13     int cnt=0;
14     for(int i=0;i<n;i++) {
15         if(i&1) Esum-=a[i];
16         else Osum-=a[i];
17         if(Oper+Esum==Eper+Osum) cnt++;
18         if(i&1) Eper+=a[i];
19         else Oper+=a[i];
20     }
21     printf("%d
",cnt);
22     return 0;
23 }
View Code

C、一个恶心的模拟?不过官方题解貌似不恶心

把矩阵位置分析一遍。然后只遍历四分之一(左上角),然后根据坐标对应4,2,1

然后就先放4再放2最后放1。

不能放的条件是放的数大于1000。

 1 #include<cstdio>
 2 #include<vector>
 3 #include<map>
 4 using namespace std;
 5 int a[1010],g[30][30];
 6 
 7 int main() {
 8     int n;
 9     scanf("%d",&n);
10     for(int i=0;i<n*n;i++) {
11         int x;
12         scanf("%d",&x);
13         a[x]++;
14     }
15     vector<pair<int,pair<int,int> > > ceils;
16     for(int i=0;i<(n+1)/2;i++) {
17         for(int j=0;j<(n+1)/2;j++) {
18             if((i!=n-i-1)&&(j!=n-j-1)) ceils.push_back({4,{i,j}});
19             else if((i!=n-i-1)^(j!=n-j-1)) ceils.push_back({2,{i,j}});
20             else ceils.push_back({1,{i,j}});
21         }
22     }
23    // printf("%d**%d
",ceils.size(),a[2]);
24     int num[3]={4,2,1};
25     for(int i=0;i<3;i++) {
26         int cnt=1;
27         for(int j=0;j<ceils.size();j++) {
28             pair<int,pair<int,int> > tmp=ceils[j];
29             int cur=tmp.first;
30             int ni=tmp.second.first;
31             int nj=tmp.second.second;
32             if(cur!=num[i]) continue;
33             while(cnt<1001&&a[cnt]<cur) cnt++;
34             if(cnt>1000) {
35                 puts("NO");
36                 return 0;
37             }
38             g[ni][nj]=g[ni][n-nj-1]=g[n-ni-1][nj]=g[n-ni-1][n-nj-1]=cnt;
39 
40             a[cnt]-=cur;
41         }
42     }
43     puts("YES");
44     for(int i=0;i<n;i++) {
45         for(int j=0;j<n;j++) printf("%d ",g[i][j]);
46         printf("
");
47     }
48     return 0;
49 }
View Code

D1、能看出来逆序是最大的,但是没有想到枚举天数来做。

D2、数据范围变大,果断二分。但是十个二分九个错。

总结两个写法。(经常写第一个,但是第二个貌似更稳)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=2e5;
 4 int n,m,a[maxn];
 5 bool cmp(int a,int b) {
 6     return a>b;
 7 }
 8 
 9 int solve(int x) {
10     int sum=0;
11     for(int j=0;j<n;j++) {
12         sum+=max(a[j]-j/x,0);
13         if(sum>=m) {
14             return 1;
15         }
16     }
17     return 0;
18 }
19 
20 int main() {
21     scanf("%d%d",&n,&m);
22     for(int i=0;i<n;i++) scanf("%d",&a[i]);
23     sort(a,a+n,cmp);
24     int l=1,r=n+1;
25     while(l<r) {
26         int mid=(l+r)/2;
27         if(solve(mid)) {
28             r=mid;
29         } else l=mid+1;
30     }
31     printf("%d
",r<=n?r:-1);
32 }
View Code
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=2e5;
 4 int n,m,a[maxn];
 5 bool cmp(int a,int b) {
 6     return a>b;
 7 }
 8 
 9 int solve(int x) {
10     int sum=0;
11     for(int j=0;j<n;j++) {
12         sum+=max(a[j]-j/x,0);
13         if(sum>=m) {
14             return 1;
15         }
16     }
17     return 0;
18 }
19 
20 int main() {
21     scanf("%d%d",&n,&m);
22     for(int i=0;i<n;i++) scanf("%d",&a[i]);
23     sort(a,a+n,cmp);
24     int l=1,r=n,ans=-1;
25     while(l<=r) {
26         int mid=(l+r)/2;
27         if(solve(mid)) {
28             ans=mid;
29             r=mid-1;
30         } else l=mid+1;
31     }
32     printf("%d
",ans);
33 }
View Code

E、看到一个题解,简单的很。。。。 最多k*(k-1) 个

构造方法,(1,2)(2,1)(1,3)(3,1)...

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main() {
 5     long long n,k;
 6     scanf("%lld%lld",&n,&k);
 7     if(n>k*(k-1)) puts("NO");
 8     else {
 9         puts("YES");
10         long long cnt=0;
11         for(int i=1;i<=k;i++) {
12             for(int j=i+1;j<=k;j++) {
13                 printf("%d %d
",i,j);
14                 cnt++;
15                 if(cnt>=n) return 0;
16                 printf("%d %d
",j,i);
17                 cnt++;
18                 if(cnt>=n) return 0;
19             }
20         }
21     }
22 }
View Code

F1、题意就是去掉一条边,是否能使剩下的两部分,没有任何一部分既有红色又有蓝色。

DFS,回溯的时候判断以u为根的子树是否符合。

用vector存图,用前向星总是超内存。。。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=3e5+10;
 4 
 5 int n,a[maxn],cnt,ans,red,blue;
 6 
 7 vector<int> G[maxn];
 8 pair<int,int> dfs(int v,int p) {
 9     int r=(a[v]==1),b=(a[v]==2);
10     for(int i=0;i<G[v].size();i++) {
11         if(G[v][i]!=p) {
12             pair<int,int> tmp=dfs(G[v][i],v);
13             ans+=(tmp.first==red&&tmp.second==0);
14             ans+=(tmp.first==0&&tmp.second==blue);
15             r+=tmp.first;
16             b+=tmp.second;
17         }
18     }
19     return make_pair(r,b);
20 }
21 
22 int main() {
23     scanf("%d",&n);
24     cnt=0,red=0,blue=0,ans=0;
25     for(int i=1;i<=n;i++) {
26         scanf("%d",&a[i]);
27         if(a[i]==1) red++;
28         else if(a[i]==2) blue++;
29     }
30     for(int i=0;i<n-1;i++) {
31         int u,v;
32         scanf("%d%d",&u,&v);
33         G[u].push_back(v);
34         G[v].push_back(u);
35     }
36     dfs(1,-1);
37     printf("%d
",ans);
38     return 0;
39 }
View Code
原文地址:https://www.cnblogs.com/ACMerszl/p/10452968.html