性质发掘+树状数组AGC006E
Posted psychicboom
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了性质发掘+树状数组AGC006E相关的知识,希望对你有一定的参考价值。
好烦啊(O(n^2))跑得比(O(nlogn))快【】
先把一些SB情况判掉
首先可以求出这个矩阵中每一列将被放到哪一列上了
于是先把列号变成目标状态趴OwO
然后你看这个(3 imes 3),每次修改只会交换奇偶性相同两列的位置,可以尝试一下分奇偶讨论,分别求出把奇偶列变成目标状态的次数,树状数组逆序对
于是设(cnt[0/1])表示列号为奇数/偶数的逆序列个数的奇偶性
注意到每次翻转会改变(cnt[中间列列号%2]),就修改一下
把列全部复位后,可以把连续五列中,在不改变其他列的情况下,把任意相隔一列的两列数同时变成逆序
具体过程见下,设列(A,B,C,D,E)分别为列(a,b,c,d,e)的逆序列:
( exttt{a b c d e})
( exttt{C B A d e})
( exttt{C B E D a})
( exttt{e b c D a})
( exttt{e b A d C})
( exttt{a B E d C})
(color{red}{ exttt{a B c D e}})
( exttt{a d C b e})
( exttt{c D A b e})
( exttt{c B a d e})
(color{red}{ exttt{A b C d e}})
最后就判断一下(cnt[0],cnt[1])是不是0就行了
代码:
#include <bits/stdc++.h>
#define N 100005
#define For(i,x,y) for(int i=(x);i<=(y);++i)
#define Rof(i,x,y) for(int i=(x);i>=(y);--i)
#define NosoL return puts("No"),0
#define SoL return puts("Yes"),0
using namespace std;
int a[4][N],cnt[2],to[N],n,c[N];
void ins(int x){ for(int i=x;i<=n;i+=(i&(-i))) c[i]++; }
int qry(int x){ int res=0;for(int i=x-1;i;i-=(i&(-i)))res+=c[i];return res; }
int main(){
scanf("%d",&n);
For(i,1,3) For(j,1,n) scanf("%d",&a[i][j]);
For(i,1,n){
if(abs(a[1][i]-a[2][i])!=1 || abs(a[2][i]-a[3][i])!=1) NosoL;
For(j,1,3) if(a[j][i]%2!=(i+3*j-3)%2) NosoL;
if(a[1][i]%3==1 && a[1][i]>a[2][i]) NosoL;
if(a[1][i]%3==0 && a[1][i]<a[2][i]) NosoL;
to[i]=(a[2][i]+1)/3;
cnt[i&1]^=(a[1][i]>a[3][i]);
}
For(i,1,n) if(to[i]%2!=i%2) NosoL;
for(int i=n-(n%2==0);i>=1;i-=2){
int x=qry(to[i]);
cnt[0]^=(x&1);
ins(to[i]);
}
For(i,1,n) c[i]=0;
for(int i=n-(n&1);i>=1;i-=2){
int x=qry(to[i]);
cnt[1]^=(x&1);
ins(to[i]);
}
if(!cnt[0] && !cnt[1]) SoL;
else NosoL;
}
以上是关于性质发掘+树状数组AGC006E的主要内容,如果未能解决你的问题,请参考以下文章