【题解】Luogu P1503 鬼子进村

平衡树好题

原题传送门

这道题要用Splay,我博客里有对Splay的详细介绍

这道题思维有点难,要把被摧毁的节点插入平衡树,而不是把没有摧毁的节点插入

先把0和n+1插入平衡树,作为边界

操作1:摧毁节点,把该点插入平衡树

操作2:修复最后一个被摧毁节点的位置的可以用栈来求出,并把该点位置从平衡树中删除

操作三:搞一个vis数组,记录是否被摧毁,如果被摧毁了,直接输出0,没被摧毁的话,输出该点后继的位置-该点前驱的位置-1,这应该也很好理解qaq

剩下就没什么问题了(除了代码有点长)

#pragma GCC optimize("O3")
#include <bits/stdc++.h>
#define root tree[0].ch[1]
#define inf 1000000005
using namespace std;
inline int read()
{
	register int x=0,f=1;register char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
	return x*f;
}
inline void write(register int x)
{
	if(!x)putchar('0');if(x<0)x=-x,putchar('-');
	static int sta[36];int cnt=0;
	while(x)sta[cnt++]=x%10,x/=10;
	while(cnt)putchar(sta[--cnt]+48);
}
inline int Min(register int a,register int b)
{
	return a<b?a:b;
}
inline int Max(register int a,register int b)
{
	return a>b?a:b;
}
struct Splay{
	int fa,ch[2],v,sum,rec;
}tree[50005];
int tot=0;
inline bool findd(register int x)
{
	return x==tree[tree[x].fa].ch[0]?0:1;
}
inline void connect(register int x,register int fa,register int son)
{
	tree[x].fa=fa;
	tree[fa].ch[son]=x;
}
inline void update(register int x)
{
	tree[x].sum=tree[tree[x].ch[0]].sum+tree[tree[x].ch[1]].sum+tree[x].rec;
}
inline void rotate(register int x)
{
	int Y=tree[x].fa;
	int R=tree[Y].fa;
	int Yson=findd(x);
	int Rson=findd(Y);
	int B=tree[x].ch[Yson^1];
	connect(B,Y,Yson);
	connect(Y,x,Yson^1);
	connect(x,R,Rson);
	update(Y),update(x);
}
inline void splay(register int x,register int to)
{
	to=tree[to].fa;
	while(tree[x].fa!=to)
	{
		int y=tree[x].fa;
		if(tree[y].fa==to)
			rotate(x);
		else if(findd(x)==findd(y))
			rotate(y),rotate(x);
		else
			rotate(x),rotate(x);
	}
}
inline int newpoint(register int v,register int fa)
{
	tree[++tot].v=v;
	tree[tot].fa=fa;
	tree[tot].sum=tree[tot].rec=1;
	return tot;
}
inline void Insert(register int x)
{
	int now=root;
	if(root==0)
	{
		newpoint(x,0);
		root=tot;
	}
	else
	{
		while(19260817)
		{
			++tree[now].sum;
			if(x==tree[now].v)
			{
				++tree[now].rec;
				splay(now,root);
				return;
			}
			int nxt=x<tree[now].v?0:1;
			if(!tree[now].ch[nxt])
			{
				int p=newpoint(x,now);
				tree[now].ch[nxt]=p;
				splay(p,root);
				return;
			}
			now=tree[now].ch[nxt];
		}
	}
}
inline int find(register int x)
{
	int now=root;
	while(19260817)
	{
		if(x==tree[now].v)
		{
			splay(now,root);
			return now;
		}
		int nxt=x<tree[now].v?0:1;
		if(!tree[now].ch[nxt])
			return 0;
		now=tree[now].ch[nxt];
	}
}
inline void delet(register int x)
{
	int pos=find(x);
	if(!pos)
		return;
	if(tree[pos].rec>1)
	{
		--tree[pos].rec;
		--tree[pos].sum;
	}
	else
	{
		if(!tree[pos].ch[0]&&!tree[pos].ch[1])
			root=0;
		else if(!tree[pos].ch[0])
		{
			root=tree[pos].ch[1];
			tree[root].fa=0;
		}
		else
		{
			int left=tree[pos].ch[0];
			while(tree[left].ch[1])
				left=tree[left].ch[1];
			splay(left,tree[pos].ch[0]);
			connect(tree[pos].ch[1],left,1);
			connect(left,0,1);
			update(left);
		}
	}
}
inline int lower(register int v)
{
	int now=root,ans=-inf;
	while(now)
	{
		if(tree[now].v<v&&tree[now].v>ans)
			ans=tree[now].v;
		if(tree[now].v>v)
			now=tree[now].ch[0];
		else
			now=tree[now].ch[1];
	}
	return ans;
}
inline int upper(register int v)
{
	int now=root,ans=inf;
	while(now)
	{
		if(tree[now].v>v&&tree[now].v<ans)
			ans=tree[now].v;
		if(tree[now].v>v)
			now=tree[now].ch[0];
		else
			now=tree[now].ch[1];
	}
	return ans;
}
bool vis[50005];
int stac[50005],top=-1;
int main()
{
	memset(vis,false,sizeof(vis));
	int n=read(),m=read();
	Insert(0);
	Insert(n+1);
	while(m--)
	{
		char ch=getchar();
		while(ch!='D'&&ch!='R'&&ch!='Q')
			ch=getchar();
		if(ch=='D')
		{
			int x=read();
			vis[x]=true;
			stac[++top]=x;
			Insert(x);
		}
		else if(ch=='R')
		{
			vis[stac[top]]=false;
			delet(stac[top--]);
		}
		else
		{
			int x=read();
			if(vis[x])
				puts("0");
			else
			{
				write(upper(x)-lower(x)-1);
				printf("\n");
			}
		}
	}
	return 0;
}
posted @ 2018-11-14 21:02  JSOI爆零珂学家yzhang  阅读(330)  评论(1编辑  收藏  举报