bzoj 2141 : 排队 (cdq分治+bit)
链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2141
思路:
其实就是求动态逆序对。。。cdq降维,用树状数组前后求两遍逆序对就好了
切水题真爽QAQ
实现代码:
#include<bits/stdc++.h> using namespace std; #define ll long long const int M = 1e5+10; int c[M<<2],a[M],b[M],ans[M]; int n,m; struct node{ int x,y,t; int kind,id; node(){} node(int a,int b,int c,int d,int e):t(a),x(b),y(c),kind(d),id(e){} bool operator < (const node &k) const { if(x == k.x) return t < k.t; return x < k.x; } }q[M],t[M]; void add(int x,int val){ while(x <= n){ c[x] += val; x += (x&-x); } } int getsum(int x){ int sum = 0; while(x){ sum += c[x]; x -= (x&-x); } return sum; } void cdq(int l,int r){ if(l >= r) return ; int mid = (l + r) >> 1; for(int i = l;i <= r;i ++){ if(q[i].t <= mid) add(q[i].y,q[i].kind); else ans[q[i].id] += q[i].kind*(getsum(n) - getsum(q[i].y)); } for(int i = l;i <= r;i ++) if(q[i].t <= mid) add(q[i].y,-q[i].kind); for(int i = r;i >= l;i --){ if(q[i].t <= mid) add(q[i].y,q[i].kind); else ans[q[i].id] += q[i].kind*(getsum(q[i].y-1)); } for(int i = r;i >= l;i --) if(q[i].t <= mid) add(q[i].y,-q[i].kind); int L = l,R = mid+1; for(int i = l;i <= r;i ++){ if(q[i].t <= mid) t[L++] = q[i]; else t[R++] = q[i]; } for(int i = l;i <= r;i ++) q[i] = t[i]; cdq(l,mid); cdq(mid+1,r); } int main() { scanf("%d",&n); for(int i = 1;i <= n;i ++){ scanf("%d",&a[i]); b[i] = a[i]; } int cnt = 0; sort(b+1,b+1+n); int len = unique(b+1,b+1+n)-b-1; for(int i = 1;i <= n;i ++){ a[i] = lower_bound(b+1,b+len+1,a[i])-b; q[++cnt] = node(cnt,i,a[i],1,0); } scanf("%d",&m); for(int i = 1;i <= m;i ++){ int x,y; scanf("%d%d",&x,&y); q[++cnt] = node(cnt,x,a[y],1,i); q[++cnt] = node(cnt,x,a[x],-1,i); q[++cnt] = node(cnt,y,a[x],1,i); q[++cnt] = node(cnt,y,a[y],-1,i); swap(a[x],a[y]); } sort(q+1,q+cnt+1); cdq(1,cnt); printf("%d\n",ans[0]); for(int i = 1;i <= m;i ++){ ans[i] += ans[i-1]; } for(int i = 1;i <= m;i ++) printf("%d\n",ans[i]); }