zoukankan      html  css  js  c++  java
  • 【做题】agc006e

    原文链接 https://www.cnblogs.com/cly-none/p/9800105.html

    题意:给出一个三行(n)列的矩阵。问它能否由满足(a_{ij} = 3(j-1) + i)的初始矩阵通过有限次中心对称其中的一个(3 imes 3)子矩阵的操作得到。

    (5 leq n leq 10^5)

    首先,我们容易发现,无论如何操作,每一列都是形如(3k+1, \, 3k+2, \, 3k+3)的3个数,并且要么是顺序要么是倒序。我们记恰是原来第(i)列的一列的权值为(i),恰是原来第(i)列上下翻转为(-i)。那么,我们每一次操作,就变成了选取相邻的3列,交换左边和右边两列的权值并把这3个权值取负。

    然后,我们还能得到偶数权值只可能存在于偶数列中,奇数权值只存在于奇数列中。

    然而,仅此还不足以成为充分条件,我们需要进一步分析。

    一般而言,这类问题的关键在于发现“不变量”,即一次操作前后都不会发生变化的量。

    于是考虑一次操作。它由两个部分组成:把所有列按奇偶性分为两组后,交换并取反一组中相邻的两列;并取反另一组中对应位置的一列。让我们先勉为其难地放弃充分性,分开考虑这两部分而忽略一部分联系:

    • 操作1:交换两个相邻元素。
    • 操作2:取反一个元素。

    这两个操作都很简洁,容易分析。

    对于操作1,通过逆序对分析我们能得到,如果初始状态和结束状态已知,那么它操作总数的奇偶性是固定的。同样,操作2也有这个性质。

    同时,我们注意到,奇数列中操作1的个数等于偶数列中操作2的个数。这意味着,奇数列的逆序对数的奇偶性与偶数列中负数个数的奇偶性相同。反之亦然。

    又是一个充分条件,但已经挺复杂了。利用搜索程序验证,在(n)很小时,这个条件是必要的。

    因此我们尝试证明这个条件是必要的。事实上,既然都写出搜索,我们就能发现在(n=5)时,这两种情况是可能的:

    [egin{matrix} -1 & 2 & -3 & 4 & 5 \ 1 & -2 & 3 & -4 & 5 end{matrix} ]

    这意味着,只要先把所有元素移动到对应位置,就可以不断任取同奇偶的两列调整正负。因为奇偶性是保证的,所以一定能得到最终状态。所以本题标算搜索

    时间复杂度(O(n log n))

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 100010;
    int mat[4][N],val[N],n,num[2],v[N];
    #define lowbit(x) ((x) & (-(x)))
    void add(int p,int val) {
      for ( ; p <= n ; p += lowbit(p))
        v[p] += val;
    }
    int query(int p) {
      int ret = 0;
      for ( ; p ; p -= lowbit(p))
        ret += v[p];
      return ret;
    }
    void fail() {
      puts("No");
      exit(0);
    }
    int main() {
      scanf("%d",&n);
      for (int i = 1 ; i <= 3 ; ++ i)
        for (int j = 1 ; j <= n ; ++ j)
          scanf("%d",&mat[i][j]);
      for (int i = 1 ; i <= n ; ++ i) {
        if (mat[1][i] % 3 == 0) {
          if (mat[2][i] == mat[1][i] - 1 && mat[3][i] == mat[1][i] - 2)
    	val[i] = - mat[1][i] / 3;
          else fail();
        } else if (mat[3][i] % 3 == 0) {
          if (mat[2][i] == mat[3][i] - 1 && mat[1][i] == mat[3][i] - 2)
    	val[i] = mat[3][i] / 3;
          else fail();
        } else fail();
      }
      for (int i = 1 ; i <= n ; i += 2) {
        if (val[i] < 0) num[1] ^= 1, val[i] = -val[i];
        if (val[i] % 2 == 0) fail();
      }
      for (int i = 2 ; i <= n ; i += 2) {
        if (val[i] < 0) num[0] ^= 1, val[i] = -val[i];
        if (val[i]&1) fail();
      }
      for (int i = 1 ; i <= n ; i += 2) {
        if ((query(n) - query(val[i]))&1) num[0] ^= 1;
        add(val[i],1);
      }
      memset(v,0,sizeof v);
      for (int i = 2 ; i <= n ; i += 2) {
        if ((query(n) - query(val[i]))&1) num[1] ^= 1;
        add(val[i],1);
      }
      if ((!num[0]) && (!num[1]))
        puts("Yes");
      else puts("No");
      return 0;
    }
    

    小结:本题的解法主要有两点存在启发性:一是推导充分条件时,可以暂时放弃充分性来得到新的推论(这和求和时引入新的(sum)有异曲同工之妙);二是一个搜索程序无伤大雅,除找规律乱搞外,还能成为解题的助力。

  • 相关阅读:
    KMP
    图论知识,博客
    POJ 2318/2398 叉积性质
    CF821 E. Okabe and El Psy Kongroo 矩阵快速幂
    CF821 D. Okabe and City 图 最短路
    CF821 C. Okabe and Boxes 栈模拟
    CF821 A. Okabe and Future Gadget Laboratory 水
    Atcoder arc077 D
    Atcoder #017 agc017 D.Game on Tree 树上NIM 博弈
    Atcoder #017 agc017 B.Moderate Differences 思维
  • 原文地址:https://www.cnblogs.com/cly-none/p/9800105.html
Copyright © 2011-2022 走看看