Codeforces Round #580 (Div. 2)赛后总结
Posted xlinyin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #580 (Div. 2)赛后总结相关的知识,希望对你有一定的参考价值。
本总结仅有A,B,C,D四题,E题作为交互题,不会!
没啥意思,因为CF只要求任意一组解,并且两个数列均为正整数,那么果断求两个数列最大值之和,这样可以保证最大值之和一定不会存在于原数列中。
#include<iostream> using namespace std; int n,m,a1=-998244353,a2=-998244353,k; int main() cin>>n; for(int i=1;i<=n;i++) cin>>k; a1=max(a1,k); cin>>m; for(int i=1;i<=m;i++) cin>>k; a2=max(a2,k); cout<<a1<<‘ ‘<<a2; return 0;
这个稍微有点意思了,果断贪心。首先将每个数都先变成离自己最近的±1,也就是正数变成1,负数变成-1,同时记录变成-1数的个数和是否有0的存在。
对于0,先将其变成1。
下面判断-1的个数Mod2是否为0,如果为0直接输出答案,否则看当前是否有0的存在。如果有0的存在,也直接输出,视为将变为1的0变成-1,cost不变。如果没有0的存在,就在原cost的基础上+2,视为将某个1变成-1.
#include<iostream> #include<cstdio> using namespace std; long long int s[100001],ans,mod,mix=998244353,maxx=-998244353,flag=0; int n; int main() cin>>n; for(int i=1;i<=n;i++) cin>>s[i]; if(s[i]>=0) ans+=max(s[i]-1,1LL*0); if(s[i]==0) flag=1; ans++; mix=min(mix,s[i]); else ans-=s[i]+1; maxx=max(maxx,s[i]); mod++; if(mod%2==0) cout<<ans; return 0; else if(flag==1) ; else ans+=2; cout<<ans; return 0;
C: Almost Equal
这个更有意思,题意可知要将这些数排成环,保证每连续N个数的和之间的差不超过1.
给出一种神奇的构造方法。假定N=3,一共6个数,分别记作a,a+1,b,b+1,c,c+1.那么a=1,b=3,c=5,
这样可以得知abc三个前缀一定要顺序排列,保证每一份均为a+b+c+x。
并且相邻两个数一定是一个带有+1,一个不带有+1(否则就会出现有一组没有+1,或者有一组3个+1)
则针对N=3的合法排列有 a,b+1,c,a+1,b,c+1;
然后我们发现 这个排列刚好是样例1N=3时给出的答案。
下面我们来考虑怎样判断不可能情况。不可能情况也就是有两个+1连在一起了,也就是N为偶数的情况。
N=4有:a,b+1,c,d+1, a+1,b,c+1,d;
可以截取:d+1---c+1 和 d---c
第一个区间==a+b+c+d+3,第二个区间==a+b+c+d+1
所以,N为偶数的情况不可取
#include<iostream> #include<cstdio> using namespace std; int n,ke[200001],cnt=0; int main() cin>>n; if(n%2==0) cout<<"NO"; return 0; for(int i=1;i<=n;i+=2) ke[i]=i*2-1; ke[i+n]=ke[i]+1; for(int i=2;i<=n;i+=2) ke[i]=i*2; ke[i+n]=ke[i]-1; cout<<"YES"<<endl; for(int i=1;i<=2*n;i++) cout<<ke[i]<<‘ ‘; return 0;
出题人备注:一个环至少有3个点
这个就有一定的坑爹之处了,众所周知求最小环是N^3的时间复杂度,那如何缩小N?
观察可知,最大的数一共60位,那么如果数字的数量超过2*60,就一定可以保证有3个点两两AND!=0;
假设前60个数在2进制上均为最高位为1,其他位为0,那么这60个数中间没有任意两个数AND!=0。但是这个时候随便来一个二进制少于60位的就一定有至少一对数字AND!=0。这个很容易理解。也很方便就可以类推到3个点。
下面就可以把N拘束在120以内了。Floyd求最小环即可!
#include<iostream> #include<cstdio> #include<cstring> using namespace std; long long int n=0,vis[100005],t,ans=0x3f3f3f3f,xl; long long int dis[201][201]; long long int edge[201][201]; long long int a[100005]; int main() cin>>t; //memset(dis,0x3f3f3f3f,sizeof(dis)); //memset(edge,0x3f3f3f3f,sizeof(edge)); for(int i=1;i<=t;i++) cin>>a[i]; if(a[i]!=0) n++; vis[n]=a[i]; if(n>2*60) cout<<3; return 0; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(((vis[i]&vis[j])!=0)&&i!=j) dis[i][j]=1; edge[i][j]=1; else dis[i][j]=edge[i][j]=0x3f3f3f3f; for(int k=1;k<=n;k++) for(int i=1;i<k;i++) for(int j=i+1;j<k;j++) ans=min(ans,dis[i][j]+edge[i][k]+edge[k][j]); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); if(ans==0x3f3f3f3f) cout<<-1; else cout<<ans; return 0;
完结撒花!
以上是关于Codeforces Round #580 (Div. 2)赛后总结的主要内容,如果未能解决你的问题,请参考以下文章
C. Almost Equal ( Codeforces Round #580 (Div. 2) )
Codeforces Round #580 (Div. 2)
Codeforces Round #580 (Div. 2)
Codeforces Round #580 (Div. 2)赛后总结