P3157 [CQOI2011]動態逆序對 CDQ分治
阿新 • • 發佈:2019-01-11
Code:
#include <cstdio> #include <algorithm> #include <cstring> #define setIO(s) freopen(s".in","r",stdin) ,freopen(s".out","w",stdout) #define maxn 1000006 using namespace std; int n,m,idx,place[maxn],C[maxn]; long long ans[maxn]; struct BIT{ int lowbit(int x) { return x&(-x); } void add(int pos,int x){ while(pos<=n) C[pos]+=x,pos+=lowbit(pos); } int ask(int pos){ int sum=0; while(pos>0) sum+=C[pos],pos-=lowbit(pos); return sum; } }tree; struct OPT{ int x,y,z,rnk,kind,id; }opt[maxn],tmp[maxn]; bool cmp(OPT i,OPT j) { return (i.x==j.x&&i.y==j.y)?(i.rnk<j.rnk):((i.x==j.x)?i.y<j.y:i.x<j.x); } void solve(int L,int R) { if(L>=R) return; int mid=(L+R)>>1,tl=L-1,tr=mid; for(int i=L;i<=R;++i){ if(opt[i].rnk<=mid&&opt[i].kind==1) tree.add(opt[i].y,opt[i].z); if(opt[i].rnk>mid&&opt[i].kind==2) ans[opt[i].id]+=tree.ask(opt[i].y)*opt[i].z; } for(int i=L;i<=R;++i) if(opt[i].rnk<=mid&&opt[i].kind==1) tree.add(opt[i].y,-opt[i].z); for(int i=L;i<=R;++i) { if(opt[i].rnk<=mid) tmp[++tl]=opt[i]; else tmp[++tr]=opt[i]; } for(int i=L;i<=R;++i) opt[i]=tmp[i]; solve(L,mid),solve(mid+1,R); } int main(){ //setIO("input"); scanf("%d%d",&n,&m); for(int i=1,a;i<=n;++i) { scanf("%d",&a); opt[++idx].x=i; opt[idx].y=a; opt[idx].z=1; opt[idx].kind=1; opt[idx].rnk=idx; place[a]=i; tree.add(a,1); ans[1]+=i-tree.ask(a); } for(int i=1;i<=n;++i) tree.add(i,-1); for(int i=1,a;i<=m;++i){ scanf("%d",&a); opt[++idx].x=place[a]; opt[idx].y=n; opt[idx].z=-1; opt[idx].kind=2; opt[idx].rnk=idx; opt[idx].id=i+1; opt[++idx].x=n; opt[idx].y=a; opt[idx].z=-1; opt[idx].kind=2; opt[idx].rnk=idx; opt[idx].id=i+1; opt[++idx].x=place[a]; opt[idx].y=a; opt[idx].z=2; opt[idx].kind=2; opt[idx].rnk=idx; opt[idx].id=i+1; opt[++idx].x=place[a]; opt[idx].y=a; opt[idx].z=-1; opt[idx].kind=1; opt[idx].rnk=idx; } sort(opt+1,opt+1+idx,cmp); solve(1,idx); for(int i=2;i<=m;++i) ans[i]+=ans[i-1]; for(int i=1;i<=m;++i) printf("%lld\n",ans[i]); return 0; }