BZOJ 3295 [CQOI2011]动态逆序对 (三维偏序CDQ+树状数组)
题目大意:
还是一道三维偏序题
每次操作都可以看成这样一个三元组 $<x,w,t>$ ,操作的位置,权值,修改时间
一开始的序列看成n次插入操作
我们先求出不删除时的逆序对总数量,再统计每次删除元素时,减少的逆序对数量
然后就是三维偏序裸题了吧,第一维时间,第二维操作位置,第三维权值,用树状数组维护即可
由于逆序对可以在被删除元素的前面或者后面,所以在归并时需要正反遍历各统计一次
1 #include <vector> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #define N1 150100 6 #define ll long long 7 #define dd double 8 #define inf 0x3f3f3f3f3f3f3f3fll 9 using namespace std; 10 11 int gint() 12 { 13 int ret=0,fh=1;char c=getchar(); 14 while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();} 15 while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();} 16 return ret*fh; 17 } 18 int n,m,nn,K; 19 20 struct node{ 21 int p,t,x,w,ans; 22 }a[N1],tmp[N1]; 23 24 struct BIT{ 25 int s[N1]; 26 void update(int x,int w){for(int i=x;i<=n;i+=(i&(-i))) s[i]+=w;} 27 int query(int x){int ans=0; for(int i=x;i;i-=(i&(-i))) ans+=s[i]; return ans;} 28 }b; 29 30 int que[N1],tl; 31 void CDQ(int L,int R) 32 { 33 if(R-L<=1) return; 34 int M=(L+R)>>1; 35 CDQ(L,M); CDQ(M,R); 36 int i,j,x,cnt; 37 38 i=M-1,j=R-1,cnt=0; 39 while(i>=L&&j>=M) 40 { 41 if(a[i].x>a[j].x){ 42 b.update(a[i].w,a[i].p); 43 que[++tl]=i; i--; 44 }else{ 45 if(a[j].p==-1) a[j].ans+=b.query(a[j].w-1); 46 j--; 47 } 48 } 49 while(i>=L) {i--;} 50 while(j>=M) {if(a[j].p==-1) a[j].ans+=b.query(a[j].w-1); j--;} 51 while(tl) {x=que[tl--]; b.update(a[x].w,-a[x].p);} 52 53 i=L,j=M,cnt=0; 54 while(i<M&&j<R) 55 { 56 if(a[i].x<a[j].x){ 57 b.update(a[i].w,a[i].p); 58 que[++tl]=i; tmp[++cnt]=a[i]; i++; 59 }else{ 60 if(a[j].p==-1) a[j].ans+=b.query(n)-b.query(a[j].w); 61 tmp[++cnt]=a[j]; j++; 62 } 63 } 64 while(i<M) {tmp[++cnt]=a[i]; i++;} 65 while(j<R) {if(a[j].p==-1) a[j].ans+=b.query(n)-b.query(a[j].w); tmp[++cnt]=a[j]; j++;} 66 while(tl) {x=que[tl--]; b.update(a[x].w,-a[x].p);} 67 68 for(i=L;i<R;i++) a[i]=tmp[i-L+1]; 69 } 70 int cmp(node s1,node s2){ 71 if(s1.p!=s2.p) return s1.p>s2.p; 72 return s1.t<s2.t;} 73 int pos[N1]; 74 75 int main() 76 { 77 scanf("%d%d",&n,&m); 78 int i; ll ans=0; nn=n+m; 79 for(i=1;i<=n;i++) a[i].w=gint(),a[i].x=i,a[i].p=1,a[i].t=i,pos[a[i].w]=i; 80 for(i=n;i>=1;i--) ans+=b.query(a[i].w),b.update(a[i].w,1); 81 memset(b.s,0,sizeof(b.s)); 82 for(i=n+1;i<=n+m;i++) a[i].w=gint(),a[i].x=pos[a[i].w],a[i].p=-1,a[i].t=i; 83 CDQ(1,n+m+1); 84 sort(a+1,a+n+m+1,cmp); 85 for(i=n+1;i<=n+m;i++) 86 { 87 printf("%lld\n",ans); 88 ans-=a[i].ans; 89 } 90 return 0; 91 }