[BZOJ3295] [Cqoi2011]动态逆序对 (cdq分治)
https://www.lydsy.com/JudgeOnline/problem.php?id=3295
思路:
第一种:我们可以按照删除的顺序变换成插入顺序 最先删除的就是最后插入的 然后就求逆序对啦
第二种:我们考虑删掉每个点对序列的贡献
设当前删除了第x个元素,那么在1−x中比它大的都要减去 在(x+1)−N中比他小的都要减去
#include<bits/stdc++.h> using namespace std; #define ll long long const int maxn = 200005; int n,m,cnt; int a[maxn],pos[maxn],tree[maxn]; ll ans[maxn]; struct node{ int t,x,val,type,id; bool friend operator<(const node u,const node v){ if(u.x==v.x) return u.val<v.val; return u.x<v.x; } }q[maxn],p[maxn]; int lowbit(int x){ return x&(-x); } void add(int x,int val){ while(x<=n){ tree[x]+=val; x+=lowbit(x); } } int get_sum(int x){ int res=0; while(x){ res+=tree[x]; x-=lowbit(x); } return res; } void cdq(int l,int r){ if(l==r) return ; int m=(l+r)>>1; for(int i=l;i<=r;i++){ if(q[i].t<=m) add(q[i].val,q[i].type); else ans[q[i].id]+=q[i].type*(get_sum(n)-get_sum(q[i].val)); } for(int i=l;i<=r;i++){ if(q[i].t<=m) add(q[i].val,-q[i].type); } for(int i=r;i>=l;i--){ if(q[i].t<=m) add(q[i].val,q[i].type); else ans[q[i].id]+=q[i].type*get_sum(q[i].val-1); } for(int i=l;i<=r;i++){ if(q[i].t<=m) add(q[i].val,-q[i].type); } int q1=l; int q2=m+1; for(int i=l;i<=r;i++){ if(q[i].t<=m) p[q1++]=q[i]; else p[q2++]=q[i]; } for(int i=l;i<=r;i++) q[i]=p[i]; cdq(l,m); cdq(m+1,r); } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); pos[a[i]]=i; q[++cnt]=node({cnt,i,a[i],1,0}); } for(int i=1;i<=m;i++){ int x; scanf("%d",&x); q[++cnt]=node({cnt,pos[x],x,-1,i}); } sort(q+1,q+1+cnt); cdq(1,cnt); for(int i=1;i<=m;i++){ printf("%lld\n",ans[i-1]); ans[i]+=ans[i-1]; } return 0; }