您的位置:首页 > 其它

【bzoj2141】 排队 树状数组+主席树

2015-08-07 19:22 176 查看
卧槽,为什么网上没有主席树的题解呀?!!!

貌似分块也可以做,但是代码会长一点吧,真心良心题不卡空间,O(nlog^2n)随便水。

结果发现自己忘考虑相同的数,一开始逆序对数求错了。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#define maxn 8000100

using namespace std;

struct yts
{
	int x,id;
}a[20010];

int lch[maxn],rch[maxn],cnt[maxn];
int root[20010],c[20010],f[20010],l[30],r[30];
int n,T,tot,mx,ans,llen,rlen;

int lowbit(int x)
{
	return x&(-x);
}

bool cmp(yts a,yts b)
{
	return a.x<b.x;
}

void add(int i,int x)
{
	while (i<=n)
	{
		c[i]+=x;
		i+=lowbit(i);
	}
}

int query(int x)
{
	int ans=0;
	for (int i=x;i;i-=lowbit(i)) ans+=c[i];
	return ans;
}

int modify(int pre,int l,int r,int x,int f)
{
	int now=++tot;
	if (l==r)
	{
		cnt[now]=cnt[pre]+f;lch[now]=rch[now]=0;
	}
	else
	{
		int mid=(l+r)/2;
		if (x<=mid)
		{
			rch[now]=rch[pre];lch[now]=modify(lch[pre],l,mid,x,f);
		}
		else
		{
			lch[now]=lch[pre];rch[now]=modify(rch[pre],mid+1,r,x,f);
		}
		cnt[now]=cnt[lch[now]]+cnt[rch[now]];
	}
	return now;
}

void modify(int x,int t,int f)
{
	for (int i=x;i<=n;i+=lowbit(i)) root[i]=modify(root[i],1,mx,t,f);
}

int askless(int L,int R,int x)
{
	if (x<L) return 0;
	if (R<=x) 
	{
		int sum=0;
		for (int i=1;i<=llen;i++) sum-=cnt[l[i]];
		for (int i=1;i<=rlen;i++) sum+=cnt[r[i]];
		return sum;
	}
	int mid=(L+R)/2;
	if (x<=mid)
	{
		for (int i=1;i<=llen;i++) l[i]=lch[l[i]];
		for (int i=1;i<=rlen;i++) r[i]=lch[r[i]];
		return askless(L,mid,x);
	}
	else
	{
		int sum=0;
		for (int i=1;i<=llen;i++) sum-=cnt[lch[l[i]]];
		for (int i=1;i<=rlen;i++) sum+=cnt[lch[r[i]]];
		for (int i=1;i<=llen;i++) l[i]=rch[l[i]];
		for (int i=1;i<=rlen;i++) r[i]=rch[r[i]];
		return sum+askless(mid+1,R,x);
	}
}

int askmore(int L,int R,int x)
{
	if (x>R) return 0;
	if (x<=L)
	{
		int sum=0;
		for (int i=1;i<=llen;i++) sum-=cnt[l[i]];
		for (int i=1;i<=rlen;i++) sum+=cnt[r[i]];
		return sum;
	}
	int mid=(L+R)/2;
	if (mid<x)
	{
		for (int i=1;i<=llen;i++) l[i]=rch[l[i]];
		for (int i=1;i<=rlen;i++) r[i]=rch[r[i]];
		return askmore(mid+1,R,x);
	}
	else
	{
		int sum=0;
		for (int i=1;i<=llen;i++) sum-=cnt[rch[l[i]]];
		for (int i=1;i<=rlen;i++) sum+=cnt[rch[r[i]]];
		for (int i=1;i<=llen;i++) l[i]=lch[l[i]];
		for (int i=1;i<=rlen;i++) r[i]=lch[r[i]];
		return sum+askmore(L,mid,x);
	}
}

void mem(int x,int y)
{
	llen=0,rlen=0;
	for (int i=x;i;i-=lowbit(i)) l[++llen]=root[i];
	for (int i=y;i;i-=lowbit(i)) r[++rlen]=root[i];
}

int main()
{
	scanf("%d",&n);
	for (int i=1;i<=n;i++) scanf("%d",&a[i].x);
	for (int i=1;i<=n;i++) a[i].id=i;
	sort(a+1,a+n+1,cmp);
	mx=1;f[a[1].id]=1;
	for (int i=2;i<=n;i++)
	{
		if (a[i].x!=a[i-1].x) mx++;
		f[a[i].id]=mx;
	}
	for (int i=n;i>=1;i--)
	{
		ans+=query(f[i]-1);
		add(f[i],1);
	}
	printf("%d\n",ans);
	
	tot=0;root[0]=cnt[0]=lch[0]=rch[0]=0;
	for (int i=1;i<=n;i++) root[i]=root[0];
	for (int i=1;i<=n;i++) modify(i,f[i],1);
	scanf("%d",&T);
	while (T--)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		if (x>y) swap(x,y);
		mem(x,y);
		ans-=askless(1,mx,f[x]-1);
		mem(x,y);
		ans-=askmore(1,mx,f[y]+1);
		mem(x,y);
		ans+=askmore(1,mx,f[x]+1);
		mem(x,y);
		ans+=askless(1,mx,f[y]-1);
		printf("%d\n",ans);
		modify(x,f[x],-1);modify(x,f[y],1);
		modify(y,f[y],-1);modify(y,f[x],1);
		swap(f[x],f[y]);
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: