【cdq分治】 BZOJ3295 [Cqoi2011]动态逆序对
题目链接:https://vjudge.net/contest/325125#problem/L
题意:求序列的逆序对,支持删除操作。
题解:从后往前扫,删除变成添加,然后每加一个数字记录添加的逆序对。找时间比他早的,id比他小的,值比他大的;以及时间比他早的,id比他大的,值比他小的。相当于三维偏序。所以跑两遍cdq即可。
上代码:
1 /************************************************************************* 2 > File Name: BZOJ3295.cpp 3 # File Name: BZOJ3295.cpp 4 # Author : xiaobuxie 5 # QQ : 760427180 6 # Email:760427180@qq.com 7 # Created Time: 2019年09月11日 星期三 20时16分01秒 8 ************************************************************************/ 9 10 #include<iostream> 11 #include<cstdio> 12 #include<map> 13 #include<cmath> 14 #include<cstring> 15 #include<set> 16 #include<queue> 17 #include<vector> 18 #include<algorithm> 19 using namespace std; 20 typedef long long ll; 21 #define inf 0x3f3f3f3f 22 #define pq priority_queue<int,vector<int>,greater<int> > 23 ll gcd(ll a,ll b){ 24 if(a<b) return gcd(b,a); 25 return b==0?a:gcd(b,a%b); 26 } 27 28 const int N=1e5+8; 29 const int M=5e4+9; 30 int opt[M]; 31 int val[N],pos[N]; 32 bool vis[N]; 33 ll tr1[N],ans[M],tr2[N]; 34 struct node{ 35 int id,x,ans,ord; 36 bool operator<(const node& o)const{ 37 return ord<o.ord; 38 } 39 }A[M+N],B[M+N]; 40 int n,m; 41 void add1(int x,int v){ for(;x;x-=x&(-x)) tr1[x]+=v;} 42 void add2(int x,int v){ for(;x<=n;x+=x&(-x)) tr2[x]+=v;} 43 ll query1(int x){ 44 ll res=0; 45 for(;x<=n;x+=x&(-x)) res+=tr1[x]; 46 return res; 47 } 48 ll query2(int x){ 49 ll res=0; 50 for(;x;x-=x&(-x)) res+=tr2[x]; 51 return res; 52 } 53 54 void cdq1(int l,int r){ 55 if(l==r) return; 56 int m=(l+r)>>1; 57 cdq1(l,m); cdq1(m+1,r); 58 for(int i=l,t1=l,t2=m+1;i<=r;++i){ 59 if(t1<=m && (t2>r || A[t1].id < A[t2].id)){ 60 add1(A[t1].x,1); 61 B[i]=A[t1]; 62 t1++; 63 } 64 else{ 65 A[t2].ans+=query1(A[t2].x); 66 B[i]=A[t2]; 67 ++t2; 68 } 69 } 70 for(int i=l;i<=m;++i) add1(A[i].x,-1); 71 for(int i=l;i<=r;++i) A[i]=B[i]; 72 } 73 void cdq2(int l,int r){ 74 if(l==r) return; 75 int m=(l+r)>>1; 76 cdq2(l,m); cdq2(m+1,r); 77 for(int i=l,t1=l,t2=m+1;i<=r;++i){ 78 if(t1<=m && (t2>r || A[t1].id > A[t2].id)){ 79 add2(A[t1].x,1); 80 B[i]=A[t1]; 81 t1++; 82 } 83 else{ 84 A[t2].ans+=query2(A[t2].x); 85 B[i]=A[t2]; 86 ++t2; 87 } 88 } 89 for(int i=l;i<=m;++i) add2(A[i].x,-1); 90 for(int i=l;i<=r;++i) A[i]=B[i]; 91 } 92 93 int main(){ 94 scanf("%d %d",&n,&m); 95 int cnt=0,anscnt=0; 96 ll tot=0; 97 int ini=0; 98 for(int i=1;i<=n;++i){ 99 scanf("%d",val+i); 100 pos[val[i]]=i; 101 } 102 for(int i=1;i<=m;++i){ 103 scanf("%d",opt+i); 104 vis[opt[i]]=1; 105 } 106 for(int i=1;i<=n;++i){ 107 if(!vis[val[i]]){ 108 ++cnt; 109 A[cnt]=(node){pos[val[i]],val[i],0,cnt}; 110 ++ini; 111 } 112 } 113 for(int i=m;i>=1;--i){ 114 ++cnt; 115 A[cnt]=(node){pos[opt[i]],opt[i],0,cnt}; 116 } 117 cdq1(1,cnt); 118 sort(A+1,A+1+cnt); 119 cdq2(1,cnt); 120 sort(A+1,A+1+cnt); 121 for(int i=1;i<=ini;++i) tot+=A[i].ans; 122 //cerr<<'a'<<tot<<endl; 123 for(int i=ini+1;i<=cnt;++i){ 124 tot+=A[i].ans; 125 ans[++anscnt]=tot; 126 //cerr<<i<<' '<<A[i].ans<<' '<<A[i].id<<' '<<A[i].x<<' '<<tot<<endl; 127 } 128 //cerr<<anscnt<<'a'<<endl; 129 for(int i=anscnt;i>=1;--i) printf("%lld\n",ans[i]); 130 return 0; 131 }