Educational Codeforces Round 55 (Rated for Div. 2)
Posted vainglory
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Educational Codeforces Round 55 (Rated for Div. 2)相关的知识,希望对你有一定的参考价值。
题意:翻书,从x到y,每次翻d页,边缘不会翻过,求最小翻书次数
题解:只有三种方式,暴力就好,注意abs(x-y)
#include<bits/stdc++.h> using namespace std; const int INF=1e9+10; int main(){ int t,n,x,y,d;scanf("%d",&t); while(t--){ scanf("%d%d%d%d",&n,&x,&y,&d); int ans=INF; if((y-x)%d==0) ans=min(ans,abs(y-x)/d); int tmp=(x-1)/d+((x-1)%d!=0); if((y-1)%d==0) ans=min(ans,tmp+(y-1)/d); tmp=(n-x)/d+((n-x)%d!=0); if((n-y)%d==0) ans=min(ans,tmp+(n-y)/d); if(ans==INF) printf("-1 "); else printf("%d ",ans); } return 0; }
题意:01串,考虑交换一次两个1的位置,求最长的连续1的个数
题解:因为只能交换一次,所以记录每一个S的位置,然后讨论间隔就好,注意内部交换
#include<bits/stdc++.h> using namespace std; const int N=1e5+10; char s[N];int pre[N]; int id[N]; int main(){ int n,sum=0;scanf("%d",&n); scanf("%s",s+1);s[0]=‘S‘,s[n+1]=‘S‘; for(int i=0;i<=n+1;i++) if(s[i]==‘S‘) pre[i]++;else sum++; for(int i=1;i<=n+1;i++) pre[i]+=pre[i-1];id[1]=0; for(int i=1;i<=n+1;i++) if(pre[i]==pre[i-1]+1) id[pre[i]]=i; int len=pre[n+1],ans=0; for(int i=1;i+2<=len;i++){ int num=id[i+2]-id[i]-1; //长度是9 if(num<=sum) ans=max(ans,num); else if(num-1==sum) ans=max(ans,sum); } for(int i=1;i+1<=len;i++) ans=max(ans,id[i+1]-id[i]-1); printf("%d ",ans); return 0; }
题意:m个专业,已知n个人的专业,以及技能点(有负数),要求选择一个集合,集合里面每个科目的人数相等,求最大技能点总和
题解:贪心选取,o(n),记录前缀,用ans[N]数组优化掉最外面的一维选取个数(这点。。emmmm常识。。。。)!!!!!
#include<bits/stdc++.h> typedef long long ll; using namespace std; const int N=1e5+10; vector<int>g[N]; vector<ll>gg[N];ll ans[N]; bool cmp(int a,int b) {return a>b;} int main(){ int n,m,x,y,max_=0;scanf("%d%d",&n,&m); int cnt=0; for(int i=1;i<=n;i++) scanf("%d%d",&x,&y),g[x].push_back(y); for(int i=1;i<=m;i++) sort(g[i].begin(),g[i].end(),cmp); for(int i=1;i<=m;i++){ for(int j=0;j<g[i].size();j++){ if(j==0) gg[i].push_back(g[i][j]); else gg[i].push_back(gg[i][j-1]+g[i][j]); } } for(int i=1;i<=m;i++)for(int j=0;j<gg[i].size();j++) if(gg[i][j]>0) ans[j+1]+=gg[i][j]; ll cmp=0; for(int i=1;i<=n;i++) cmp=max(cmp,ans[i]); printf("%lld ",cmp); return 0; }
题意:构造题。给定n个点的最大度数,构造一个图拥有最大直径
题解:特别像高中的时候的同分异构体的构造,直接考虑度大于2的点连成串,度等于1的点加进去就好了。
#include<bits/stdc++.h> using namespace std; const int N=1e5+10; int a[N];set<int>se; vector<pair<int,int> >g; int main(){ int n,num=0;scanf("%d",&n); for(int i=1;i<=n;i++) {scanf("%d",&a[i]);if(a[i]==1) num++,se.insert(i);} if(num==0){printf("YES %d ",n-1);printf("%d ",n-1);for(int i=1;i<n;i++) printf("%d %d ",i,i+1);return 0;} if(num==n){ printf("NO ");return 0;} set<int>tt;for(int i=1;i<=n;i++) tt.insert(i);for(auto it:se) tt.erase(it); int t=*se.begin();auto it=tt.begin();if(tt.size()!=0) se.erase(t); while(it!=tt.end()) {g.push_back({t,*it});a[t]--;t=*it,it++;a[t]--;} if(num>=2) {g.push_back({t,*se.rbegin()});a[t]--,a[*se.rbegin()]--;se.erase(*se.rbegin());} int len=g.size();it=tt.begin(); while(se.size()!=0){ while(a[*it]==0&&it!=tt.end()) it++; if(it==tt.end()) break; g.push_back({*it,*se.begin()}); se.erase(se.begin());a[*it]--; } if(se.size()!=0) {printf("NO ");return 0;} printf("YES %d ",len);printf("%d ",g.size()); for(auto it:g) printf("%d %d ",it.first,it.second); return 0; }
题意:n个数的序列,一次操作将某个区间加上一个数,求最终c的个数的最大值
题解:说实话这个题当时没想清楚。。。emmmm.就觉得有地方能优化,这提示问题想不清楚的时候要多对他进行建模,从简单的模型,一步步构造出来,
记sum[i]为1~i中c的个数,cnt[i]为1-i中x的个数,那么对于[l,r]来操作,答案变为 sum[n]-sum[r]+sum[l-1]+cnt[r]-cnt[l-1],观察可发现对于一个给定的r的位置
,与其有关的仅仅是max(sum[l-1]-cnt[l-1]),这样之后就可以用o(n)的dp进行搞了。。。。说实话对这些dp还不是很熟悉。。。。一时想不到答案
题解:过的人数是个位数,打扰了
题解:codeforces 1082G. Petya and Graph(网络流,最大权闭合子图)
收获:感觉这场写完之后收获比较大的地方有以下的地方:
C题的错误示范T+优化(就是n个数,1<=a[i]<=m)这种的o(n)写法,以后不至于纠结
E题的启发吧。算是。。好像就是写一下,分析下,估计现在还达不到那个水平
G题的网络流:最大权闭合子图的相关模型和知识点
以上是关于Educational Codeforces Round 55 (Rated for Div. 2)的主要内容,如果未能解决你的问题,请参考以下文章
Educational Codeforces Round 7 A
Educational Codeforces Round 7
Educational Codeforces Round 90
Educational Codeforces Round 33