【bzoj3295】动态逆序对 CDQ分治

AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=3295

【题解】

这题很神。

我用的是popoqqq大爷的做法。

具体见http://blog.csdn.net/popoqqq/article/details/38761287

感觉这种做法似乎应该称为整体二分?

#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
#define FILE "read"
#define MAXN 100010
#define up(i,j,n) for(int i=j;i<=n;++i)
#define dn(i,j,n) for(int i=j;i>=n;--i)
#define cmax(a,b) a=max(a,b)
#define cmin(a,b) a=min(a,b)
struct node{
	int x,y,pos;
	bool operator < (const node &b) const {return y=r)  return;
	int mid=(l+r)>>1,ta(l),tb(mid+1),j(l);
	up(i,l,r) stack[(q[i].pos<=mid?ta:tb)++]=q[i];
	up(i,l,r) q[i]=stack[i];
	CDQ(l,mid);  tot++;
	up(i,mid+1,r){
		for(;j<=mid&&q[j].y=l&&q[j].y>q[i].y;--j) updata(q[j].x,1);
		f[q[i].pos]+=get(q[i].x,-1);
	}
	CDQ(mid+1,r);
	ta=l;tb=mid+1;  
    up(i,l,r) if((q[ta]r)&&ta<=mid) stack[i]=q[ta++];  
	else stack[i]=q[tb++];  
	up(i,l,r)  q[i]=stack[i];
}
int main(){
	freopen(FILE".in","r",stdin);
	freopen(FILE".out","w",stdout);
	n=read();  m=read();
	up(i,1,n)  a[i]=read(),b[a[i]]=i;
	up(i,1,n){
		cnt[i]=get(a[i],1);
		updata(a[i],-1);
		ans+=cnt[i];
	}
	tot++;
	dn(i,n,1){
		cnt[i]+=get(a[i],-1);
		updata(a[i],1);
	}
	up(i,1,m)q[i].x=read(),q[i].y=b[q[i].x],q[i].pos=i;
	sort(q+1,q+m+1);  CDQ(1,m);
	sort(q+1,q+m+1,cmp);
	up(i,1,m){
		printf("%lld\n",ans);
		ans-=cnt[q[i].y];
		ans+=f[i];
	}
	return 0;
}


你可能感兴趣的:(bzoj,CDQ分治)