[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 }

 

posted @ 2018-01-02 07:54  skylee03  阅读(129)  评论(0编辑  收藏  举报