zoukankan      html  css  js  c++  java
  • [agc006E]Rotate 3x3

    Description

    给你一个3*N的网格,位置为(i,j)的网格上的数为i+3(j-1)。每次选一个3*3的网格旋转180度,问最后能否使得网格(i,j)的值为ai,j。(5N105

    如图:

    Solution

    依图可看出,所谓的旋转就是将选择的3*3网格左右列交换,并且3列都进行翻转。

    设正列(如1,2,3)为小写字母,反列(如3,2,1)为大写字母。

    假如有相邻5列:

    a b c d e

    C B A d e

    C B E D a

    e b c D a

    e b A d C

    a B E d C

    a B c D e

    a d C b e

    c D A b e

    c B a d e

    A b C d e

    我们可以在有5列可供操纵的情况下将任意相隔1列的两列翻转而不影响其他。

    在最终答案中设下标为奇的反列个数为x,下表为偶的个数为y。

    先不考虑翻转问题,将奇列和偶列分开考虑(因为在处理奇列的时候只会翻转却不会影响偶列的具体数值)。由于如果初始矩阵操作后变为矩阵a,则矩阵a一定能变为初始矩阵,我们按照列的权值从小到大将矩阵a恢复为初始矩阵。处理奇列时,每翻转一次,就会翻转一个偶列,偶列也是同样道理。我们计算出奇列、偶列被翻转次数的奇偶性,与x、y比较即可。

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    using namespace std;
    int n,a[3][100010];
    int need_swap[2],real_swap[2];
    int num[100010],id[100010];
    int tree[100010];
    void add(int _id,int x){for(;_id<=n;_id+=_id&-_id) tree[_id]+=x;}
    int query(int _id){int re=0;for(;_id;_id-=_id&-_id) re+=tree[_id];return re;}
    int main()
    {
        scanf("%d",&n);
        for (int j=0;j<3;j++)
        for (int i=1;i<=n;i++) 
            scanf("%d",&a[j][i]);
        for (int i=1;i<=n;i++)
        for (int j=0;j<3;j++)
        {
            if ((a[0][i]^i)&1) { printf("No");return 0;}
            if (a[0][i]==a[1][i]+1&&a[1][i]==a[2][i]+1&&a[2][i]%3!=0) 
            {
                need_swap[i&1]++;num[i]=a[2][i]/3+1;id[num[i]]=i;continue;
            }
            if (a[0][i]==a[1][i]-1&&a[1][i]==a[2][i]-1&&a[0][i]%3!=0) 
            {
                num[i]=a[0][i]/3+1;id[num[i]]=i;continue;
            }
            printf("No");return 0;
        }
        int cnt;
        for (int i=1;i<=n;i+=2)
        {
            cnt=id[i]+2*(i/2-query(id[i]));
            real_swap[0]+=abs(i-cnt)/2;
            add(id[i],1);
        }
        memset(tree,0,sizeof(tree));
        for (int i=2;i<=n;i+=2)
        {
            cnt=id[i]+2*(i/2-1-query(id[i]));
            real_swap[1]+=abs(i-cnt)/2;
            add(id[i],1);
        }
        real_swap[0]%=2;real_swap[1]%=2;need_swap[0]%=2;need_swap[1]%=2;
        if (real_swap[0]!=need_swap[0]||real_swap[1]!=need_swap[1]) printf("No");
        else printf("Yes");
    }
  • 相关阅读:
    (转)描述线程与进程的区别?
    Python学习笔记:ceil、floor、round、int取整
    Python学习笔记:SQL中group_concat分组合并操作实现
    Python学习笔记:pd.rank排序
    函数声明
    Dictionary 介绍
    Tuple介绍
    List介绍
    DataGridView 如何退出 编辑状态
    C#实现打印与打印预览功能
  • 原文地址:https://www.cnblogs.com/coco-night/p/9487925.html
Copyright © 2011-2022 走看看