【树套树】【BZOJ 2141】排队

题目

【树套树】【BZOJ 2141】排队_第1张图片

思路

【树套树】【BZOJ 2141】排队_第2张图片

代码

#include
#define N 200002
#define M 5000002
using namespace std;
int n,m,q[N],ans;
int hs[N],tot,num[M];
int sum[M],root[N],ls[M],rs[M],sz;
void insert(int &k,int l,int r,int w,int f)
{
     
	if(!k)k=++sz;sum[k]+=f;
	if(l==r)return;
	int mid=(l+r)>>1;
	if(w<=mid)insert(ls[k],l,mid,w,f);
	else insert(rs[k],mid+1,r,w,f);
}
int query(int &k,int l,int r,int a,int b)
{
     
	if(!k)return 0;int mid=(l+r)>>1;
	if(a<=l&&b>=r)return sum[k];
	if(b<=mid)return query(ls[k],l,mid,a,b);
	else if(a>mid)return query(rs[k],mid+1,r,a,b);
	else return query(ls[k],l,mid,a,mid)+query(rs[k],mid+1,r,mid+1,b);
}
void ins(int pos,int w,int f)
{
     
	int l=1,r=tot,k=1;
	while(l!=r)
	{
     
		int mid=(l+r)>>1;
		insert(root[k],1,n,pos,f);
		if(w<=mid)k=k<<1,r=mid;
		else k=k<<1|1,l=mid+1;
	}insert(root[k],1,n,pos,f);
}
int ask_bit(int a,int b,int w)
{
     
	int l=1,r=tot,k=1,ret=0;
	while(l!=r)
	{
     
		int mid=(l+r)>>1;
		if(w<=r&&w>mid)
		{
     
			ret+=query(root[k<<1],1,n,a,b);
			k=k<<1|1,l=mid+1;
		}
		else
			k=k<<1,r=mid;
	}return ret;
} 
int ask_big(int a,int b,int w)
{
     
	int l=1,r=tot,k=1,ret=0;
	while(l!=r)
	{
     
		int mid=(l+r)>>1;
		if(w>=l&&w<=mid)
		{
     
			ret+=query(root[k<<1|1],1,n,a,b);
			k=k<<1,r=mid;
		}
		else k=k<<1|1,l=mid+1;
	}return ret;
}
int x[N],y[N],cnt;
void init()
{
     
	for(int i=1;i<=n;i++)
	{
     
		scanf("%d",&q[i]);
		num[++cnt]=q[i];
	}scanf("%d",&m);
	for(int i=1;i<=m;i++)
	{
     
		scanf("%d%d",&x[i],&y[i]);
		num[++cnt]=x[i];
		num[++cnt]=y[i];
	}sort(num+1,num+1+cnt);
	num[0]=-(1<<30);
	for(int i=1;i<=cnt;i++)
		if(num[i]!=num[i-1])
			hs[++tot]=num[i];
}
int find(int x)
{
     
	int l=1,r=tot,ret;
	while(l<=r)
	{
     
		int mid=(l+r)>>1;
		if(hs[mid]<=x)
			l=mid+1,ret=mid;
		else r=mid-1;
	}
	return ret;
}
int main()
{
     
	scanf("%d",&n);init();
	for(int i=1;i<=n;i++)
	{
     
		int ii=find(q[i]);
		ans+=ask_big(1,i,ii);
		ins(i,ii,1);
	}
	printf("%d\n",ans);
	for(int i=1;i<=m;i++)
	{
     
		int a=x[i],b=y[i];
		if(a>b)swap(a,b);
		int ia=find(q[a]),ib=find(q[b]);
		ans-=ask_big(a+1,b,ib);
		ans+=ask_bit(a+1,b,ib);
		ans-=ask_bit(a,b-1,ia);
		ans+=ask_big(a,b-1,ia);
		if(ia>ib)ans--;
		else if(ia<ib)ans++;
		ins(a,ia,-1);ins(b,ib,-1);
		ins(a,ib,1);ins(b,ia,1);
		swap(q[a],q[b]);
		printf("%d\n",ans);
	}
}

你可能感兴趣的:(【树套树】【BZOJ 2141】排队)