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
