CodeForces 785E 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 }