BZOJ 3196 二逼平衡树 ——树套树

【题目分析】

    全靠运气,卡空间。

    xjb试几次就过了。

【代码】

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

#define maxn 200005
#define mlog 16
#define inf 0x3f3f3f3f
#define maxm 4000005
#define F(i,j,k) for (int i=j;i<=k;++i)

int ch[maxm][2],fa[maxm],siz[maxm],v[maxm],num[maxm],n,m,rt[maxn*5],a[maxn];
int L,R,X,C,tot,Pre,Nxt,opt,ans,k,aim;

void update(int k)
{siz[k]=siz[ch[k][0]]+siz[ch[k][1]]+num[k];}

int ins(int &k,int fat)
{
	if (!k){k=++tot;num[k]=siz[k]=1;v[k]=C;fa[k]=fat;ch[k][0]=ch[k][1]=0;return k;}
	siz[k]++; 
	if (C==v[k]) {num[k]++;return k;}
	else if (C<v[k]) return ins(ch[k][0],k);
	else return ins(ch[k][1],k);
}

void rot(int x,int &k)
{
	int y=fa[x],z=fa[y],l=0,r;
	if (ch[y][1]==x) l=1; r=l^1;
	if (y==k) k=x;
	else
	{
		if (ch[z][0]==y) ch[z][0]=x;
		else ch[z][1]=x;
	}
	fa[x]=z; fa[y]=x; fa[ch[x][r]]=y;
	ch[y][l]=ch[x][r]; ch[x][r]=y;
	update(y); update(x);
	
}

void splay(int x,int &k)
{
	while (x!=k)
	{
		int y=fa[x],z=fa[y];
		if (y!=k)
		{
			if (ch[z][0]==y^ch[y][0]==x) rot(x,k);
			rot(y,k);
		}
		rot(x,k);
	}
}

void add(int o,int l,int r)
{
	int mid=l+r>>1;
	splay(ins(rt[o],0),rt[o]);
	if (l==r) return;
	if (X<=mid) add(o<<1,l,mid);
	else add(o<<1|1,mid+1,r);
}

void qrk(int k)
{
	if (!k) return;
	if (v[k]<C) {ans+=siz[ch[k][0]]+num[k];return qrk(ch[k][1]);}
	if (v[k]==C) {ans+=siz[ch[k][0]];return;}
	return qrk(ch[k][0]);
}

void queryrk(int o,int l,int r)
{
	if (L<=l&&r<=R){qrk(rt[o]);return;}
	int mid=l+r>>1;
	if (L<=mid) queryrk(o<<1,l,mid);
	if (R>mid) queryrk(o<<1|1,mid+1,r);
}

void qpr(int k)
{
	if (!k) return;
	if (v[k]>=C) return qpr(ch[k][0]);
	else{Pre=max(Pre,v[k]); return qpr(ch[k][1]);}
}

void querypr(int o,int l,int r)
{
	if (L<=l&&r<=R){qpr(rt[o]);return;}
	int mid=l+r>>1;
	if (L<=mid) querypr(o<<1,l,mid);
	if (R>mid) querypr(o<<1|1,mid+1,r);
}

void qnt(int k)
{
	if (!k) return;
	if (v[k]<=C) return qnt(ch[k][1]);
	else{Nxt=min(Nxt,v[k]); return qnt(ch[k][0]);}
}

void querynt(int o,int l,int r)
{
	if (L<=l&&r<=R){qnt(rt[o]);return;}
	int mid=l+r>>1;
	if (L<=mid) querynt(o<<1,l,mid);
	if (R>mid) querynt(o<<1|1,mid+1,r);
}

void del(int &k)
{
	if (v[k]==C)
	{
		if (num[k]>1)
		{
			num[k]--;
			siz[k]--;
			splay(k,rt[aim]);
			return ;
		}
		else
		{
			if (ch[k][0]*ch[k][1]==0)
			{
				if ((!ch[k][0])&&(!ch[k][1])) {k=0;return;}
				if (!ch[k][0]) fa[ch[k][1]]=fa[k];
				else fa[ch[k][0]]=fa[k];
				k=ch[k][0]+ch[k][1];
				return ;
			}
			else
			{
				int tmp=rand()%2;
				rot(ch[k][tmp],k);
				del(k);
				return ;
			}
		}
	}
	siz[k]--;
	if (v[k]<C) del(ch[k][1]);
	else del(ch[k][0]);
}

void dec(int o,int l,int r)
{
	int mid=(l+r)/2;aim=o;
	del(rt[o]);
	if (l==r) return ;
	if (X<=mid) dec(o<<1,l,mid);
	else dec(o<<1|1,mid+1,r);
}

int main()
{
	int l,r;
//	freopen("in.txt","r",stdin);
	scanf("%d%d",&n,&m);
	F(i,1,n)
	{
		scanf("%d",&a[i]);
		X=i; C=a[i];
		add(1,1,n);
	}
	F(i,1,m)
	{
		scanf("%d",&opt);
		switch(opt)
		{
			case 1:
				ans=0;
				scanf("%d%d%d",&L,&R,&C);
				queryrk(1,1,n);
				printf("%d\n",ans+1);
			break;
			case 2:
				scanf("%d%d%d",&L,&R,&k);
				l=-inf; r=inf;
				while (l<r)
				{
					int mid=(l+r)/2+1;
					C=mid; ans=0;
					queryrk(1,1,n);
					if (ans<=k-1) l=mid;
					else r=mid-1;
				}
				printf("%d\n",r);
			break;
			case 3:
				scanf("%d%d",&X,&k);
				C=a[X];
				dec(1,1,n);
				a[X]=k; C=a[X];
				add(1,1,n);
			break;
			case 4:
				Pre=-inf;
				scanf("%d%d%d",&L,&R,&C);
				querypr(1,1,n);
				printf("%d\n",Pre);
			break;
			case 5:
				Nxt=inf;
				scanf("%d%d%d",&L,&R,&C);
				querynt(1,1,n);
				printf("%d\n",Nxt);
			break;
		}
	}
}

  

posted @ 2017-02-14 23:05  SfailSth  阅读(156)  评论(0编辑  收藏  举报