题目链接: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 刚好。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 typedef long long ll; 5 6 //#define mytest 7 8 int main() { 9 #ifdef mytest 10 freopen("in.txt","r",stdin); 11 freopen("out.txt","w",stdout); 12 #endif // mytest 13 14 int q,n,a[201],h[400]; 15 scanf("%d",&q); 16 while(q--) { 17 scanf("%d",&n); 18 memset(h,0,sizeof h);//必须重置 19 20 bool ans=false; 21 for(int i=1; i<=n; i++) { 22 scanf("%d",&a[i]); 23 } 24 25 if(n==2||n==3){//这俩一定连续 26 printf("YES\n"); 27 continue; 28 } 29 30 a[0]=a[n];//便于作差 31 for(int i=1;i<=n;i++){ 32 h[a[i]-a[i-1]+200]++; 33 } 34 if(h[201]+h[1-n+200]==n||h[199]+h[n-1+200]==n)//计算两种情况的检查点 35 ans=true; 36 37 if(ans) { 38 printf("YES\n"); 39 } else { 40 printf("NO\n"); 41 } 42 } 43 return 0; 44 }