BZOJ3295:[CQOI2011]動態逆序對
阿新 • • 發佈:2018-12-24
淺談樹狀陣列與線段樹:https://www.cnblogs.com/AKMer/p/9946944.html
題目傳送門:https://www.lydsy.com/JudgeOnline/problem.php?id=3295
樹狀陣列套線段樹,如題目所言,動態維護答案即可。
寫了樹套樹之後我才發現遞迴是個多麼傻逼的玩意兒……
時間複雜度:\(O(nlog^2n)\)
空間複雜度:\(O(nlogn)\)
程式碼如下:
#include <cstdio> using namespace std; typedef long long ll; #define low(i) ((i)&(-(i))) const int maxn=1e5+5; ll ans; int n,m; int pos[maxn]; inline int read() { int x=0,f=1;char ch=getchar(); for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1; for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0'; return x*f; } struct segment_tree { int tot; int ls[maxn*85],rs[maxn*85],sum[maxn*85]; inline int query(int p,int l,int r,int pos,int opt) { int res=0; while(l!=r) { int mid=(l+r)>>1; if(pos<=mid) { if(opt)res+=sum[rs[p]]; p=ls[p],r=mid; } else { if(!opt)res+=sum[ls[p]]; p=rs[p],l=mid+1; } } return res; } inline void change(int p,int l,int r,int pos,int v) { if(!p)p=++tot; while(1) { sum[p]+=v;if(l==r)break; int mid=(l+r)>>1; if(pos<=mid) { if(!ls[p])ls[p]=++tot; p=ls[p],r=mid; } else { if(!rs[p])rs[p]=++tot; p=rs[p],l=mid+1; } } } }T; struct TreeArray { int rt[maxn]; inline int query(int pos,int v,int opt) { int res=0; for(int i=pos;i;i-=low(i)) res+=T.query(rt[i],1,n,v,opt); return res; } inline void change(int pos,int x,int v) { for(int i=pos;i<=n;i+=low(i)) { if(!rt[i])rt[i]=++T.tot; T.change(rt[i],1,n,x,v); } } }bit; int main() { n=read(),m=read(); for(int i=1;i<=n;i++) { int x=read();pos[x]=i; ans+=bit.query(i-1,x,1); bit.change(i,x,1); } for(int i=1;i<=m;i++) { printf("%lld\n",ans); int x=read(); ans-=bit.query(pos[x]-1,x,1); ans-=bit.query(n,x,0)-bit.query(pos[x],x,0); bit.change(pos[x],x,-1); } return 0; }