BZOJ 3295 动态逆序对 CDQ分治
这就是我声明中说的那道CDQ题目...
在经过一番重写之后,我A了.
至于题解,网上的题解写的都不错.
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<ctime> #include<string> #include<iomanip> #include<algorithm> #include<map> using namespace std; #define LL long long #define FILE "dealing" #define up(i,j,n) for(int i=j;i<=n;++i) #define db double #define ull unsigned long long #define eps 1e-10 #define pii pair<int,int> int read(){ int x=0,f=1,ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return f*x; } const int maxn=200010,maxm=20000,limit=1e6,inf=(int)(2e9),mod=(int)(7+1e9+0.1); template<class T>bool cmax(T& a,T b){return a<b?a=b,true:false;} template<class T>bool cmin(T& a,T b){return a>b?a=b,true:false;} template<class T>T min(T& a,T& b){return a<b?a:b;} template<class T>T max(T& a,T& b){return a>b?a:b;} int n,m; struct node{ int v,t,id; LL ans; }a[maxn],w[maxn]; int id[maxn],c[maxn]; int lowbit(int x){return x&-x;} int getsum(int x){ int ans=0; while(x){ ans+=c[x]; x-=lowbit(x); } return ans; } void add(int x,int d){ while(x<=n){ c[x]+=d; x+=lowbit(x); } } void init(){ n=read(),m=read();int top=n; up(i,1,n)a[i].v=read(),id[a[i].v]=i,a[i].id=i; up(i,1,m){ int v=read(); a[id[v]].t=top--; } up(i,1,n)if(!a[i].t)a[i].t=top--; } bool cmp3(node a,node b){return a.id<b.id;} int q[maxn],top=0; void cdq(int l,int r){ if(l==r)return; int mid=(l+r)>>1; cdq(l,mid); cdq(mid+1,r); int pos1=l,pos2=mid+1; while(pos1<=mid||pos2<=r){ if((a[pos1].id<a[pos2].id&&pos1<=mid)||pos2>r){ add(n-a[pos1].v+1,1); q[++top]=n-a[pos1].v+1; pos1++; continue; } if((a[pos1].id>a[pos2].id&&pos2<=r)||pos1>mid){ a[pos2].ans+=getsum(n-a[pos2].v+1); pos2++; } } while(top)add(q[top--],-1); pos1=mid,pos2=r; while(pos1>=l||pos2>=mid+1){ if((a[pos1].id>a[pos2].id&&pos1>=l)||(pos2<mid+1)){ add(a[pos1].v,1); q[++top]=a[pos1].v; pos1--; continue; } if((a[pos1].id<a[pos2].id&&pos2>=mid+1)||(pos1<l)){ a[pos2].ans+=getsum(a[pos2].v); pos2--; } } while(top)add(q[top--],-1); pos1=l,pos2=mid+1;int u=l-1; while(pos1<=mid||pos2<=r){ if((a[pos1].id<a[pos2].id&&pos1<=mid)||pos2>r){ w[++u]=a[pos1]; pos1++; continue; } if((a[pos1].id>a[pos2].id&&pos2<=r)||pos1>mid){ w[++u]=a[pos2]; pos2++; } } up(i,l,r)a[i]=w[i]; } bool cmp(node a,node b){return a.t<b.t;} LL ans[maxn]; void solve(){ sort(a+1,a+n+1,cmp); cdq(1,n); sort(a+1,a+n+1,cmp); up(i,1,n)ans[i]=ans[i-1]+a[i].ans; for(int i=n;i>=n-m+1;i--)printf("%lld\n",ans[i]); } int main(){ freopen(FILE".in","r",stdin); freopen(FILE".out","w",stdout); init(); solve(); return 0; }