[CF911D]Inversion Counting
题目大意:
给你一个数列,翻转其中一个区间,问每次翻转过后逆序对个数的奇偶性。
思路:
首先树状数组求出一开始的奇偶性,然后考虑每次翻转对答案的贡献。
对于整个区间,我们可以把翻转转化成若干次交换。
也就是交换(l,r),(l+1,r-1)...
总共有(r-l+1)/2次。
考虑每一次交换对答案的影响。
设当前交换的数为(a,b),那么对于a,改变的逆序对数为区间[a,b]大于a的数与小于a的数之差,对于b同理。
由于只要求奇偶性,那么加和减都差不多,所以我们可以都变成加法,那么a和b造成影响的总和是2(b-a),肯定是偶数。
再算上(a,b)本身一对,肯定是奇数。
这样我们就对答案有(r-l+1)/2次奇数的变化,看一下(2-l+1)/2是奇数还是偶数,然后和答案异或起来即可。
1 #include<cstdio> 2 #include<cctype> 3 inline int getint() { 4 register char ch; 5 while(!isdigit(ch=getchar())); 6 register int x=ch^'0'; 7 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 8 return x; 9 } 10 const int N=1501; 11 int n; 12 class FenwickTree { 13 private: 14 int val[N]; 15 int lowbit(const int &x) const { 16 return x&-x; 17 } 18 public: 19 void modify(int p) { 20 while(p<=n) { 21 val[p]++; 22 p+=lowbit(p); 23 } 24 } 25 int query(int p) const { 26 int ret=0; 27 while(p) { 28 ret+=val[p]; 29 p-=lowbit(p); 30 } 31 return ret; 32 } 33 }; 34 FenwickTree t; 35 int main() { 36 n=getint(); 37 int cnt=0; 38 for(register int i=1;i<=n;i++) { 39 const int x=getint(); 40 cnt+=t.query(n-x+1); 41 t.modify(n-x+1); 42 } 43 bool ans=cnt&1; 44 for(register int m=getint();m;m--) { 45 const int l=getint(),r=getint(); 46 ans^=(r-l+1)>>1&1; 47 puts(ans?"odd":"even"); 48 } 49 return 0; 50 }