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

题意:给出一个三行\(n\)列的矩阵。问它能否由满足\(a_{ij} = 3(j-1) + i\)的初始矩阵通过有限次中心对称其中的一个\(3 \times 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\)时,这两种情况是可能的:

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

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

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

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int N = 100010;
  4. int mat[4][N],val[N],n,num[2],v[N];
  5. #define lowbit(x) ((x) & (-(x)))
  6. void add(int p,int val) {
  7. for ( ; p <= n ; p += lowbit(p))
  8. v[p] += val;
  9. }
  10. int query(int p) {
  11. int ret = 0;
  12. for ( ; p ; p -= lowbit(p))
  13. ret += v[p];
  14. return ret;
  15. }
  16. void fail() {
  17. puts("No");
  18. exit(0);
  19. }
  20. int main() {
  21. scanf("%d",&n);
  22. for (int i = 1 ; i <= 3 ; ++ i)
  23. for (int j = 1 ; j <= n ; ++ j)
  24. scanf("%d",&mat[i][j]);
  25. for (int i = 1 ; i <= n ; ++ i) {
  26. if (mat[1][i] % 3 == 0) {
  27. if (mat[2][i] == mat[1][i] - 1 && mat[3][i] == mat[1][i] - 2)
  28. val[i] = - mat[1][i] / 3;
  29. else fail();
  30. } else if (mat[3][i] % 3 == 0) {
  31. if (mat[2][i] == mat[3][i] - 1 && mat[1][i] == mat[3][i] - 2)
  32. val[i] = mat[3][i] / 3;
  33. else fail();
  34. } else fail();
  35. }
  36. for (int i = 1 ; i <= n ; i += 2) {
  37. if (val[i] < 0) num[1] ^= 1, val[i] = -val[i];
  38. if (val[i] % 2 == 0) fail();
  39. }
  40. for (int i = 2 ; i <= n ; i += 2) {
  41. if (val[i] < 0) num[0] ^= 1, val[i] = -val[i];
  42. if (val[i]&1) fail();
  43. }
  44. for (int i = 1 ; i <= n ; i += 2) {
  45. if ((query(n) - query(val[i]))&1) num[0] ^= 1;
  46. add(val[i],1);
  47. }
  48. memset(v,0,sizeof v);
  49. for (int i = 2 ; i <= n ; i += 2) {
  50. if ((query(n) - query(val[i]))&1) num[1] ^= 1;
  51. add(val[i],1);
  52. }
  53. if ((!num[0]) && (!num[1]))
  54. puts("Yes");
  55. else puts("No");
  56. return 0;
  57. }

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

【做题】agc006e - Rotate 3x3——分析&思维的更多相关文章

  1. 2017国家集训队作业[agc006e]Rotate 3x3

    2017国家集训队作业[agc006e]Rotate 3x3 题意: ​ 给你一个\(3*N\)的网格,每次操作选择一个\(3*3\)的网格,旋转\(180^\circ\).问可不可以使每个位置\(( ...

  2. 【做题】CF177G2. Fibonacci Strings——思维+数列

    题意:定义斐波那契字符串为: $f_1 = $ "a" \(f_2 =\) "b" \(f_n = f_{n-1} + f_{n-2}, \, n > 2 ...

  3. 【做题】arc070_f-HonestOrUnkind——交互+巧妙思维

    做的第一道交互题-- 首先,有解的一个必要条件是\(a>b\).否则,即当\(a<=b\)时,可以有\(a\)个unkind的人假装自己就是那\(a\)个honest的人.(彼此之间都说是 ...

  4. [AGC006E] Rotate 3x3 树状数组+贪心

    Description ​ XFZ在北京一环内有一套房. ​ XFZ房子的地砖呈网格状分布,是一个3∗N3∗N的网格.XFZ在买下这套房时,每个地砖上有一个数字,位置为(i,j)(i,j)的地砖上的数 ...

  5. [agc006E]Rotate 3x3

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

  6. AtCoder Grand Contest 1~10 做题小记

    原文链接https://www.cnblogs.com/zhouzhendong/p/AtCoder-Grand-Contest-from-1-to-10.html 考虑到博客内容较多,编辑不方便的情 ...

  7. noip做题记录+挑战一句话题解?

    因为灵巧实在太弱辽不得不做点noip续下命QQAQQQ 2018 积木大赛/铺设道路 傻逼原题? 然后傻逼的我居然检查了半天是不是有陷阱最后花了差不多一个小时才做掉我做过的原题...真的傻逼了我:( ...

  8. 判断s2是否能够被通过s1做循环移位(rotate)得到的字符串是否包含

    问题:给定两个字符串s1和s2,要求判断s2是否能够被通过s1做循环移位(rotate)得到的字符串包含.例如,S1=AABCD和s2=CDAA,返回true:给定s1=ABCD和s2=ACBD,返回 ...

  9. C语言程序设计做题笔记之C语言基础知识(下)

    C 语言是一种功能强大.简洁的计算机语言,通过它可以编写程序,指挥计算机完成指定的任务.我们可以利用C语言创建程序(即一组指令),并让计算机依指令行 事.并且C是相当灵活的,用于执行计算机程序能完成的 ...

随机推荐

  1. js 图片与base64互相转换

    js将图片转化为base64 参考地址:http://www.cnblogs.com/mr-wuxiansheng/p/6931077.html var img = "imgurl" ...

  2. python使用matplotlib绘制折线图教程

    Matplotlib是一个Python工具箱,用于科学计算的数据可视化.借助它,Python可以绘制如Matlab和Octave多种多样的数据图形.下面这篇文章主要介绍了python使用matplot ...

  3. UML关系实现、泛化,依赖、组合

    图片via<大话设计模式> UML一目了然

  4. Win7局域网内共享文件设置方式

    1.右键-->打开网络和共享中心 2.打开网络和共享中心-->单击更改高级共享设置 3.选中文件(夹)-->属性->共享 4.共享-->添加用户,并赋予相应权限 5.选中 ...

  5. python语法_算数运算+赋值运算符+比较运算符+逻辑运算符

    算术运算符 + - * /  加减乘除 5/2 = 2.5 5//2 = 2  整除,地板除 5%2= 1 取余数 2**10 指数运算 2的10次方 算术优先级 无论多少级,都使用()小括号进行优先 ...

  6. RFID系统 免费开源代码 开发,分享[申明:来源于网络]

    RFID系统 免费开源代码 开发,分享[申明:来源于网络] 地址:http://www.codeforge.cn/s/0/RFID%E7%B3%BB%E7%BB%9F

  7. Android开发网【申明:来源于网络】

    Android开发网[申明:来源于网络] 地址:http://www.jizhuomi.com/android/video/

  8. 悬线法 || BZOJ3039: 玉蟾宫 || Luogu P4147 玉蟾宫

    题面: P4147 玉蟾宫 题解:过于板子举报了 #include<cstdio> #include<cstring> #include<iostream> #de ...

  9. spark streaming集成flume

    1. 安装flume flume安装,解压后修改flume_env.sh配置文件,指定java_home即可. cp hdfs jar包到flume lib目录下(否则无法抽取数据到hdfs上): $ ...

  10. xss脚本绕过限制的方法

    第一关:第一关比较简单,直接写入标签就可以,这里不多说了,payload如下: http://sqler.win/xss/level1.php?name=test%3Csvg/onload=alert ...