bzoj3295 [Cqoi2011]动态逆序对
cdq分治。
代码
#include<cstdio> #include<algorithm> #define N 200010 #define lb(x) (x&-x) using namespace std; int n,b[N],a[N],id[N],ans[N],i,m,L[N],R[N],c[N]; long long Ans; struct g{ int v,typ; }v[N]; bool cmp(g a,g b) { return a.v<b.v; } void cc(int x,int w) { while (x<=n) { c[x]+=w; x+=lb(x); } } int sum(int x) { int ans=0; while (x) { ans+=c[x]; x-=lb(x); } return ans; } void solve(int l,int r) { int m,i,tot=0,cnt=0; if (l>=r) return; m=(l+r)>>1; for (i=l;i<=m;i++) { v[++tot].typ=0; v[tot].v=b[i]; } for (i=m+1;i<=r;i++) { v[++tot].typ=i; v[tot].v=b[i]; } sort(v+1,v+1+tot,cmp); for (i=tot;i>=1;i--) if (v[i].typ) ans[v[i].typ]+=sum(id[v[i].v]); else cc(id[v[i].v],1); for (i=1;i<=tot;i++) if (v[i].typ==0) cc(id[v[i].v],-1); for (i=1;i<=tot;i++) if (v[i].typ) ans[v[i].typ]+=cnt-sum(id[v[i].v]); else { cnt++; cc(id[v[i].v],1); } for (i=1;i<=tot;i++) if (v[i].typ==0) cc(id[v[i].v],-1); solve(l,m); solve(m+1,r); } int main() { scanf("%d%d",&n,&m); for (i=1;i<=n;i++) { scanf("%d",&a[i]); id[a[i]]=i; } for (i=1;i<=n;i++) { L[i]=sum(n)-sum(a[i]); cc(a[i],1); } for (i=1;i<=n;i++) c[i]=0; for (i=n;i>=1;i--) { R[i]=sum(a[i]); cc(a[i],1); } for (i=1;i<=n;i++) c[i]=0; for (i=1;i<=n;i++) Ans=Ans+L[i]; for (i=1;i<=m;i++) scanf("%d",&b[i]); solve(1,m); for (i=1;i<=m;i++) { printf("%lld\n",Ans); Ans=Ans-L[id[b[i]]]-R[id[b[i]]]+ans[i]; } }