Codeforces Round #709 (Div. 2, based on Technocup 2021 Final Round)(C~D)(队列模拟循环
C. Basic Diplomacy
这题的构造条件其实相当宽松。只要先判断一个人的只能选择那个人的天数是否大于(m+1)/2。(即对于1个数有11,11,11,11,212。那么只能选择1的天数为4天)如果有人满足这个条件,则返回NO,否则一定可以构造一个序列满足条件。因为若没有一个人的只能选择天数大于(m+1)/2.则将只能选择一个人的天数的人选敲定后,剩余的天数中一定可以选出一个不同的人来防止越界。
AC代码如下:
#include<bits/stdc++.h> #define MAXN 100005 using namespace std; typedef long long ll; typedef pair<int,int> pii; int t,n,m,cnt[MAXN],ans[MAXN]; vector<int>a[MAXN]; int main(){ scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); int len; for(int i=1;i<=m;++i){ scanf("%d",&len); if(len==1){//如果这一天是只能选择一个人 int temp; scanf("%d",&temp); ++cnt[temp];//那个人的cnt++ ans[i]=temp;//那一天的答案为temp a[i].push_back(temp); }else{//否则的话 for(int j=0;j<len;j++){ int temp; scanf("%d",&temp); a[i].push_back(temp);//把这一天可以选择的人都列入vector } } } int flag=0; for(int i=1;i<=n;++i) if(cnt[i]>(m+1)/2){//如果有个数的cnt大于了(m+1)/2.就说明不行 flag=1; break; } if(flag) printf("NO\n"); else{//如果可行的话就能构造 for(int i=1;i<=m;++i){ if(a[i].size()==1) continue;//如果该天只能选择一个人,就跳过 int pos=0; while(cnt[a[i][pos]]==(m+1)/2) ++pos;/*找到第一个cnt小于(m+1)/2的。 注意不可能有两个数都等于这个, 否则的话就说明每天都只有一个人可以选择 */ ++cnt[a[i][pos]];//找到后令这一天只能选这个数,即这个数的唯一选择天数++ ans[i]=a[i][pos];//令这一天对应的答案为这个数 } printf("YES\n"); for(int i=1;i<=m;++i) printf("%d ",ans[i]);//输出答案 printf("\n"); } memset(ans,0,sizeof(ans)); memset(cnt,0,sizeof(cnt)); for(int i=1;i<=m;i++) a[i].clear(); } return 0; }
D. Playlist(队列维护)
用一个nex数组记录与该数对比的那个数下标。将所有的相邻两个gcd=1的数对入列,并将右边的数删除,再判断左边的数和右边的右边的数的gcd,再入列即可。由于队列先进先出的特点,故可以用来模拟圈中转完一轮再看下一轮的特点。需要注意的是需要先判断一下左边的那个数在前面有没有被删除过,被删除过了则continue即可。
AC代码如下:
#include<bits/stdc++.h> #define MAXN 100005 using namespace std; typedef long long ll; typedef pair<int,int> pii; int t,n,m,a[MAXN],nex[MAXN],del[MAXN],ans[MAXN]; int gcd(int a,int b){return (b==0)?a:gcd(b,a%b);} queue<int>q; int main(){ scanf("%d",&t); while(t--){ scanf("%d",&n); memset(del,0,sizeof(del)); memset(ans,0,sizeof(ans)); for(int i=0;i<n;i++)//0~n-1 .nex数组的初始化 nex[i]=(i+1)%n; for(int i=0;i<n;i++) scanf("%d",&a[i]); for(int i=0;i<n;i++) if(gcd(a[i],a[nex[i]])==1) q.push(i); int cnt=0; while(!q.empty()){ int u=q.front(); q.pop(); if(del[u]) continue; del[nex[u]]=1; ans[++cnt]=nex[u]+1; nex[u]=nex[nex[u]];//右边的数已经被删除了,更新右边的数 if(gcd(a[u],a[nex[u]])==1) q.push(u); } printf("%d ",cnt); for(int i=1;i<=cnt;i++) printf("%d ",ans[i]); printf("\n"); } return 0; }

浙公网安备 33010602011771号