Codeforces Round #579 (Div. 3) A. Circle of Students
题目链接:A. Circle of Students
可以简单的转化成这样一个问题。n 个人围坐一圈(第 1 位至第 n 位),第 i 位同学的情绪值 x i( 1 <= x i <= n,为整数),且他们的情绪值互不相同。给出第 1 位同学到第 n 位同学的情绪值 x ,问:从 第1 位同学开始,他们的情绪值是不是严格连续(递减或递增)的,这里认为 1->n 和 n->1 是连续的。还有他们是坐成一圈,如果数组存的话,数组首尾记录的情绪值是相邻的,要连续。
4 5 1 2 3----作为参考
那么,除了 1->n 和 n->1 的组,两两相邻的情绪值相差 1 。n 个人,相邻的作差一次(前面的数 - 后面的数,或者反过来都可以,下文以 后 - 前 为例)会有 n 个结果。这 n 个结果肯定满足这样的条件:
- n-1 个 1,1 个 1-n 共 n 个 顺时针坐的情况
- n-1 个 -1,1 个 n-1 共 n 个 逆时针坐的情况
所以我们作差,利用差的 hash 计算检查点的和是不是 n 。且题目数据规模小,无意中允许我们使用hash,只是有负值。但是,数据规模最大 200 ,不难发现,最小的负值为 1-200 ,最大的正值为 200-1 ,所以计算的差值统统加上 200,数组开到 400 刚好。
#include <bits/stdc++.h> using namespace std; typedef long long ll; //#define mytest int main() { #ifdef mytest freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); #endif // mytest int q,n,a[201],h[400]; scanf("%d",&q); while(q--) { scanf("%d",&n); memset(h,0,sizeof h);//必须重置 bool ans=false; for(int i=1; i<=n; i++) { scanf("%d",&a[i]); } if(n==2||n==3){//这俩一定连续 printf("YES\n"); continue; } a[0]=a[n];//便于作差 for(int i=1;i<=n;i++){ h[a[i]-a[i-1]+200]++; } if(h[201]+h[1-n+200]==n||h[199]+h[n-1+200]==n)//计算两种情况的检查点 ans=true; if(ans) { printf("YES\n"); } else { printf("NO\n"); } } return 0; }