【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 }
View Code

 

posted @ 2019-09-12 14:30  小布鞋  阅读(130)  评论(0编辑  收藏  举报