CodeForces 785E Anton and Permutation

Anton and Permutation

题意:给定一个 1-n的排列, 现在有m次操作, 每次操作交换 a[l],a[r] 求交换完之后整个序列的逆序对数是多少。

题解:

树状数组套主席树去维护。 感觉是一个主席树 + 树状数组套动态开点的线段树啊。 好久没写主席树了 都不会写了。。。

每次交换 a[l] 和 a[r] 以后 有影响的只有区间[l, r]里面的数。

代码:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
  4 #define LL long long
  5 #define ULL unsigned LL
  6 #define fi first
  7 #define se second
  8 #define pb push_back
  9 //#define lson l,m,rt<<1
 10 //#define rson m+1,r,rt<<1|1
 11 #define max3(a,b,c) max(a,max(b,c))
 12 #define min3(a,b,c) min(a,min(b,c))
 13 typedef pair<int,int> pll;
 14 const int INF = 0x3f3f3f3f;
 15 const LL mod =  (int)1e9+7;
 16 const int N = 2e5 + 100;
 17 const int M = N * 100;
 18 int rt[N], S[N], lson[M], rson[M], cnt[M];
 19 int tot;
 20 int a[N];
 21 void PushUp(int x){
 22     cnt[x] = cnt[lson[x]] + cnt[rson[x]];
 23 }
 24 int Build(int l, int r){
 25     int x = ++tot;
 26     cnt[x] = 0;
 27     if(l < r){
 28         int m = l+r >> 1;
 29         lson[x] = Build(l, m);
 30         rson[x] = Build(m+1, r);
 31         PushUp(x);
 32     }
 33     return x;
 34 }
 35 int Update(int l, int r, int pre, int pos, int v){
 36 
 37     int x = ++tot;
 38     cnt[x] = cnt[pre] + v;
 39     if(l < r){
 40         int m = l+r >> 1;
 41         if(pos <= m){
 42             rson[x] = rson[pre];
 43             lson[x] = Update(l, m, lson[pre], pos, v);
 44         }
 45         else {
 46             lson[x] = lson[pre];
 47             rson[x] = Update(m+1, r, rson[pre], pos, v);
 48         }
 49         PushUp(x);
 50     }
 51     return x;
 52 }
 53 int Query(int l, int r, int L, int rt){
 54     if(!rt) return 0;
 55     if(l == r) return cnt[rt];
 56     int m = l + r >> 1;
 57     if(L <= m) return Query(l, m, L,lson[rt]);
 58     return cnt[lson[rt]] + Query(m+1, r, L, rson[rt]);
 59 }
 60 void Insert(int l,int r,int &i,int x,int val)
 61 {
 62     if( i==0) i = ++tot;
 63     cnt[i] += val;
 64     if(l == r) return ;
 65     int m = l+r >>1;
 66     if(x <= m) Insert(l, m, lson[i], x, val);
 67     else Insert(m+1, r, rson[i], x, val);
 68 }
 69 int lowbit(int x){
 70     return x&(-x);
 71 }
 72 int main(){
 73     tot = 0;
 74     int n, m;
 75     scanf("%d%d", &n, &m);
 76     int tmp = 0;
 77     rt[0] = Build(1, n);
 78     for(int i = 0; i <= n; i++) a[i] = i;
 79     for(int i = 1; i <= n; i++) rt[i] = Update(1, n, rt[i-1], i, 1);
 80     LL ans = 0;
 81     int l, r;
 82     while(m--){
 83         scanf("%d%d", &l, &r);
 84         if(l == r) {
 85             printf("%I64d\n", ans);
 86             continue;
 87         }
 88         if(l > r) swap(l, r);
 89         if(l + 1 < r){
 90             int len = r - l - 1;
 91             int t1 = Query(1, n, a[r], rt[r-1]) - Query(1, n, a[r], rt[l]);
 92             for(int i = l; i ;i -= lowbit(i)) t1 -= Query(1, n, a[r], S[i]);
 93             for(int i = r-1; i;i -= lowbit(i)) t1 += Query(1, n, a[r], S[i]);
 94             int t2 = len - t1;
 95             ans += t1;
 96             ans -= t2;
 97             t1 = Query(1, n, a[l],rt[r-1]) - Query(1, n, a[l], rt[l]);
 98             for(int i = l; i > 0;i -= lowbit(i)) t1 -= Query(1, n, a[l], S[i]);
 99             for(int i = r-1; i > 0;i -= lowbit(i)) t1 += Query(1, n, a[l], S[i]);
100             t2= len-t1;
101             ans -= t1;
102             ans += t2;
103 
104         }
105         if(a[l] < a[r]) ans++;
106         else ans--;
107         printf("%I64d\n", ans);
108         for(int j = l; j <= n; j += lowbit(j)){
109             Insert(1, n, S[j], a[l],-1);
110             Insert(1, n, S[j], a[r], 1);
111         }
112         for(int j = r; j <= n; j += lowbit(j)){
113             Insert(1, n, S[j], a[l], 1);
114             Insert(1, n, S[j], a[r], -1);
115         }
116         swap(a[l], a[r]);
117     }
118     return 0;
119 }
View Code

猜你喜欢

转载自www.cnblogs.com/MingSD/p/9496255.html