CDQ分治
首先可以将答案分为之前有的逆序对数量+此操作产生的逆序对数量
那么最后前缀和即可
由于题目直接给出的是删除操作,并且加上初始序列的插入操作
有两种不同会对答案造成影响的操作,不容易处理
那么考虑从后往前考虑,那么删除操作就变成插入操作
先将所有要删的数删完剩下的数,把它们作为初始序列
然后进行CQD分治
产生逆序对要求是
$time_{i}<time_{j},val_{i}<val_{j},pos_{i}>pos_{j}$
或$time_{i}<time_{j},val_{i}>val_{j},pos_{i}<pos_{j}$
三维偏序问题
在CDQ分治过程中,正的扫一遍,倒着扫一遍即可
1 #include <bits/stdc++.h> 2 #define int long long 3 using namespace std; 4 const int N=1e5+100; 5 int n,m,a[N],b[N],ans[N]; 6 int p[N],w,dfn,tree[N],ti[N]; 7 struct node 8 { 9 int ti,pos,val,id; 10 }sh[N]; 11 node t[N]; 12 int lowbit(int x) 13 { 14 return x&(-x); 15 } 16 void change(int x,int v) 17 { 18 while (x<=n) 19 { 20 if (ti[x]!=dfn) 21 { 22 ti[x]=dfn; 23 tree[x]=0; 24 } 25 tree[x]+=v; 26 x+=lowbit(x); 27 } 28 } 29 int query(int x) 30 { 31 int ans=0; 32 while (x>0) 33 { 34 if (ti[x]==dfn) ans+=tree[x]; 35 x-=lowbit(x); 36 } 37 return ans; 38 } 39 int ask(int l,int r) 40 { 41 return query(r)-query(l-1); 42 } 43 void cdq(int l,int r) 44 { 45 if (l==r) return; 46 int mid=(l+r)>>1; 47 cdq(l,mid); 48 cdq(mid+1,r); 49 dfn++; 50 int tl=l,tr=mid+1; 51 for (int i=l;i<=r;i++) 52 { 53 if ((tl<=mid && sh[tl].pos<sh[tr].pos) || tr>r) 54 { 55 change(sh[tl].val,1); 56 tl++; 57 } 58 else 59 { 60 ans[sh[tr].id]+=ask(sh[tr].val+1,n); 61 tr++; 62 } 63 } 64 dfn++;//注意要将树状数组清零 65 tl=mid;tr=r;//倒着统计 66 for (int i=l;i<=r;i++) 67 { 68 if ((tl>=l && sh[tl].pos>sh[tr].pos) || tr<=mid) 69 { 70 change(sh[tl].val,1); 71 tl--; 72 } 73 else 74 { 75 ans[sh[tr].id]+=ask(1,sh[tr].val-1); 76 tr--; 77 } 78 } 79 tl=l;tr=mid+1; 80 for (int i=l;i<=r;i++) 81 { 82 if ((tl<=mid && sh[tl].pos<sh[tr].pos) || tr>r) t[i]=sh[tl++]; 83 else t[i]=sh[tr++]; 84 }//以pos为第二维从小到大归并排序 85 for (int i=l;i<=r;i++) sh[i]=t[i]; 86 } 87 signed main() 88 { 89 scanf("%lld%lld",&n,&m); 90 for (int i=1;i<=n;i++) 91 scanf("%lld",&a[i]); 92 for (int i=1;i<=m;i++) 93 scanf("%lld",&b[i]); 94 for (int i=1;i<=m;i++) p[b[i]]=1; 95 for (int i=1;i<=n;i++) 96 { 97 if (p[a[i]]==0) 98 { 99 w++; 100 sh[w].ti=w; 101 sh[w].val=a[i]; 102 sh[w].pos=i; 103 sh[w].id=0;//原序列统计在一起,作为初始值 104 } 105 else p[a[i]]=i; 106 } 107 for (int i=m;i>=1;i--)//进行操作 108 { 109 w++; 110 sh[w].ti=w; 111 sh[w].val=b[i]; 112 sh[w].pos=p[b[i]]; 113 sh[w].id=m-i+1; 114 } 115 cdq(1,w); 116 for (int i=1;i<=m;i++) ans[i]+=ans[i-1]; 117 for (int i=m;i>=1;i--) 118 printf("%lld\n",ans[i]); 119 }
来源:https://www.cnblogs.com/huangchenyan/p/12248453.html