平衡树(模板)(Splay)

原题:洛谷P3369 普通平衡树

小的注意点:grank函数(比x小的数的个数+1)中,对答案的计算要在splay之前。

#include<bits/stdc++.h>
#define R register int
#define ll long long
#define I inline
using namespace std;
const int N=1e5+3;
int rt,tt,tot;
struct node
{
	int val,cnt,sz;
	int son[2],fa;
};
node t[N];
I void update(int x){t[x].sz=t[x].cnt+t[t[x].son[0]].sz+t[t[x].son[1]].sz;}
I bool getw(int x){return t[t[x].fa].son[1]==x;}
I void rotate(int x)
{
	R y=t[x].fa,z=t[y].fa;
	bool w=getw(x);
	if(z)t[z].son[getw(y)]=x;
	t[x].fa=z;
	R &s=t[x].son[!w];
	t[s].fa=y;t[y].son[w]=s;
	t[y].fa=x;s=y;
	update(y);
}
void splay(int x,int to)
{
	if(!x)return;
	for(R y;(y=t[x].fa)!=to;rotate(x))
		if(t[y].fa!=to)rotate(getw(x)==getw(y)?y:x);
	if(!to)rt=x;
	update(x);
}
int find(int v)
{
	R p;
	for(p=rt;p&&t[p].val!=v;p=t[p].son[t[p].val<v]);
	return splay(p,0),p;
}
void insert(int v)
{
	++tot;
	if(!rt)
	{
		rt=++tt;
		t[rt].cnt=t[rt].sz=1;
		t[rt].val=v;
		return;
	}
	R p=rt,q; bool o;
	while(p)
	{
		if(t[p].val==v)
		{
			splay(p,0);
			++t[p].cnt;++t[p].sz;
			return;
		}
		q=p; p=t[p].son[o=t[p].val<v];
	}
	t[q].son[o]=++tt;
	t[tt].val=v;
	t[tt].fa=q;
	splay(tt,0);
	++t[tt].cnt;++t[tt].sz;
}
void erase(int v)
{
	R p=find(v);
	if(!p)return;
	if(t[p].cnt>1)
	{
		--t[p].cnt;
		--t[p].sz;
		return;
	}
	--tot;
	R q=t[p].son[0];
	if(!q)
	{
		t[rt=t[p].son[1]].fa=0;
		return;
	}
	while(t[q].son[1])q=t[q].son[1];
	splay(q,p);
	t[q].son[1]=t[p].son[1];
	rt=t[t[p].son[1]].fa=q;
	t[q].fa=0;
	update(q); 
}
int grank(int v)
{
	R ans=0,p=rt;
	bool o;
	while(p)
	{
		if(v==t[p].val)
		{
			int res=ans+t[t[p].son[0]].sz+1;
			splay(p,0);//***
			return res;
		}
		o=t[p].val<v;
		if(o)ans+=t[t[p].son[0]].sz+t[p].cnt;
		p=t[p].son[o];
	}
	return ans+1;
}
int arank(int k)
{
	if(k>tot)return 0;
	R p=rt;
	while(1)
	{
		const R c0=t[t[p].son[0]].sz,c1=t[p].cnt+c0;
		if(k>c0&&k<=c1)break;
		if(k<=c0)p=t[p].son[0];
		else p=t[p].son[1],k-=c1;
	}
	return splay(p,0),p;
}
int lower(int v)
{
	R p=rt,id=0;
	while(p)
	{
		if(t[p].val>=v)p=t[p].son[0];
		else id=p,p=t[p].son[1];
	}
	return splay(id,0),id;
}
int upper(int v)
{
	R p=rt,id=0;
	while(p)
	{
		if(t[p].val<=v)p=t[p].son[1];
		else id=p,p=t[p].son[0];
	}
	return splay(id,0),id;
}
int main()
{
	int n;
	scanf("%d",&n);
	for(R i=1;i<=n;i++)
	{
		int op,x;
		scanf("%d%d",&op,&x);
		if(op==1)insert(x);
		else if(op==2)erase(x);
		else if(op==3)printf("%d\n",grank(x));
		else if(op==4)printf("%d\n",t[arank(x)].val);
		else if(op==5)printf("%d\n",t[lower(x)].val);
		else printf("%d\n",t[upper(x)].val);
	}
	return 0;
}

原题:洛谷P3391 文艺平衡树

注意点:与上面类似,在访问子节点信息时记得先下传标记

#include<bits/stdc++.h>
#define R register int
#define ll long long
#define I inline
using namespace std;
const int N=1e5+3;
int rt=1,tt,a[N];
struct node
{
	int val,sz;
	int son[2],fa;
	bool rev;
};
node t[N];
I void update(int x){t[x].sz=1+t[t[x].son[0]].sz+t[t[x].son[1]].sz;}
I bool getw(int x){return t[t[x].fa].son[1]==x;}
I void rotate(int x)
{
	R y=t[x].fa,z=t[y].fa;
	bool w=getw(x);
	if(z)t[z].son[getw(y)]=x;
	t[x].fa=z;
	R &s=t[x].son[!w];
	t[s].fa=y;t[y].son[w]=s;
	t[y].fa=x;s=y;
	update(y);
}
void splay(int x,int to)
{
	if(!x)return;
	for(R y;(y=t[x].fa)!=to;rotate(x))
		if(t[y].fa!=to)rotate(getw(x)==getw(y)?y:x);
	if(to==0)rt=x;
	update(x);
}
I void pushdown(int p)
{
	swap(t[p].son[0],t[p].son[1]);
	t[t[p].son[0]].rev^=1;t[t[p].son[1]].rev^=1;
	t[p].rev=0;
}
int build(int fa,int l,int r)
{
	if(l>r)return 0;
	int mid=l+r>>1,p=++tt;
	t[p].val=mid;
	t[p].fa=fa;
	t[p].son[0]=build(p,l,mid-1);
	t[p].son[1]=build(p,mid+1,r);
	update(p);
	return p;
}
int arank(int k)
{
	R p=rt;
	while(p)
	{
		if(t[p].rev)pushdown(p);//***
		const R c=t[t[p].son[0]].sz+1;
		if(k==c)break;
		if(k<c)p=t[p].son[0];
		else p=t[p].son[1],k-=c;
	}
	return p;
}
void reverse(int l,int r)
{
	int x=arank(l),y=arank(r+2);
	splay(y,0);splay(x,y);
	t[t[x].son[1]].rev^=1;
}
int o;
void dfs(int p)
{
	if(!p)return;
	if(t[p].rev)pushdown(p);
	dfs(t[p].son[0]);
	a[o++]=t[p].val;
	dfs(t[p].son[1]);
}
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	build(0,0,n+1);
	for(R i=1;i<=m;i++)
	{
		int l,r;
		scanf("%d%d",&l,&r);
		reverse(l,r);
	}
	dfs(rt);
	for(R i=1;i<=n;i++)printf("%d ",a[i]);
	return 0;
}
posted @ 2021-02-24 00:05  nkxjlym  阅读(68)  评论(0)    收藏  举报