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 个结果肯定满足这样的条件:

  1. n-1 个 1,1 个 1-n 共 n 个  顺时针坐的情况
  2. 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;
}

 

posted @ 2019-09-02 20:19  yooonn  阅读(253)  评论(0编辑  收藏  举报