1. 程式人生 > >BZOJ 3295 [CQOI2011]動態逆序對 (三維偏序CDQ)

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 }