bzoj 4825: [Hnoi2017]单旋【dfs序+线段树+hash】

这个代码已经不是写丑那么简单了……脑子浆糊感觉np++分分钟想暴起打死我……就这还一遍A过了……
先都读进来hash一下,因为是平衡树所以dfs序直接按照点值来就好
对于每个操作:
1:set维护已插入的值,对新加入的x找到它的前驱后继,选深度大的挂上去(画图找规律,我也不知道为什么深度较浅的一定挂不上去
2、3:对于这个节点x的右子树,深度不变,x深度变为1,其他点深度+1
4、5:先做2、3操作,然后在set里把这个点删掉,整棵树的深度-1
并不是很难但是情况比较多,导致main函数奇丑无比……

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<set>
using namespace std;
const int N=100005;
int n,ha[N],a[N],tot,has,m,f[N],c[N][2],root;
set<int>st;
typedef set<int>::iterator it;
struct qwe
{
	int l,r,de;
}t[N<<2];
struct wen
{
	int o,x;
}q[N];
int read()
{
	int r=0,f=1;
	char p=getchar();
	while(p>'9'||p<'0')
	{
		if(p=='-')
			f=-1;
		p=getchar();
	}
	while(p>='0'&&p<='9')
	{
		r=r*10+p-48;
		p=getchar();
	}
	return r*f;
}
void pd(int ro)
{
	if(t[ro].de)
	{
		t[ro<<1].de+=t[ro].de;
		t[ro<<1|1].de+=t[ro].de;
		t[ro].de=0;
	}
}
void build(int ro,int l,int r)
{
	t[ro].l=l,t[ro].r=r;
	if(l==r)
		return;
	int mid=(l+r)>>1;
	build(ro<<1,l,mid);
	build(ro<<1|1,mid+1,r);
}
void jia(int ro,int l,int r,int w)
{
	if(l>r)
		return;
	if(t[ro].l==l&&t[ro].r==r)
	{
		t[ro].de+=w;
		return;
	}
	pd(ro);
	int mid=(t[ro].l+t[ro].r)>>1;
	if(r<=mid)
		jia(ro<<1,l,r,w);
	else if(l>mid)
		jia(ro<<1|1,l,r,w);
	else
	{
		jia(ro<<1,l,mid,w);
		jia(ro<<1|1,mid+1,r,w);
	}
}
void update(int ro,int w,int d)
{
	if(t[ro].l==t[ro].r)
	{
		t[ro].de=d;
		return;
	}
	pd(ro);
	int mid=(t[ro].l+t[ro].r)>>1;
	if(w<=mid)
		update(ro<<1,w,d);
	else if(w>mid)
		update(ro<<1|1,w,d);
}
int ques(int ro,int w)
{
	if(t[ro].l==t[ro].r)
		return t[ro].de;
	pd(ro);
	int mid=(t[ro].l+t[ro].r)>>1;
	if(w<=mid)
		return ques(ro<<1,w);
	else if(w>mid)
		return ques(ro<<1|1,w);
}
void add(int x,int y,int d)
{
	int de=ques(1,x);
	c[x][d]=y;
	update(1,y,de+1);
	f[y]=x;
	st.insert(y);
	printf("%d\n",de+1);
}
int main()
{
	n=read();
	for(int i=1;i<=n;i++)
	{
		q[i].o=read();
		if(q[i].o==1)
			q[i].x=read(),a[++tot]=q[i].x;
	}
	sort(a+1,a+1+tot);
	for(int i=1;i<=tot;i++)
		if(i==1||a[i]!=a[i-1])
			ha[a[i]]=++has;
	for(int i=1;i<=n;i++)
		if(q[i].o==1)
			q[i].x=ha[q[i].x];
	build(1,1,tot);
	for(int i=1;i<=n;i++)
	{
		if(q[i].o==1)
		{
			if(st.empty())
			{
				update(1,q[i].x,1);
				st.insert(q[i].x);
				f[q[i].x]=0;
				root=q[i].x;
				puts("1");
			}
			else
			{
				it ne=st.lower_bound(q[i].x);
				if(ne==st.begin())
					add(*ne,q[i].x,0);
				else
				{
					it pr=ne;
					pr--;
					if(ne==st.end()||ques(1,*pr)>ques(1,*ne))
						add(*pr,q[i].x,1);
					else
						add(*ne,q[i].x,0);
				}
			}
		}
		else if(q[i].o==2)
		{
			it now=st.begin();
			int x=*now,d=ques(1,x);
			printf("%d\n",d);
			if(d==1)
				continue;
			jia(1,1,x-1,1);
			jia(1,f[x],tot,1);
			update(1,x,1);
			int rc=c[x][1],p=f[x];
			f[x]=0;
			c[p][0]=rc;
			if(rc)
				f[rc]=p;
			c[x][1]=root;
			f[root]=x;
			root=x;
		}
		else if(q[i].o==3)
		{
			it now=st.end();
			now--;
			int x=*now,d=ques(1,x);
			printf("%d\n",d);
			if(d==1)
				continue;
			jia(1,1,f[x],1);
			jia(1,x+1,tot,1);
			update(1,x,1);
			int lc=c[x][0],p=f[x];
			f[x]=0;
			c[p][1]=lc;
			if(lc)
				f[lc]=p;
			c[x][0]=root;
			f[root]=x;
			root=x;
		}
		else if(q[i].o==4)
		{
			it now=st.begin();
			int x=*now,d=ques(1,x);
			st.erase(x);
			printf("%d\n",d);
			if(d==1)
			{
				root=c[x][1];
				f[root]=0;
				jia(1,1,tot,-1);
				continue;
			}
			jia(1,x+1,f[x]-1,-1);
			int rc=c[x][1],p=f[x];
			f[x]=0;
			c[p][0]=rc;
			if(rc)
				f[rc]=p;
		}
		else
		{
			it now=st.end();
			now--;
			int x=*now,d=ques(1,x);
			st.erase(x);
			printf("%d\n",d);
			if(d==1)
			{
				root=c[x][0];
				f[root]=0;
				jia(1,1,tot,-1);
				continue;
			}
			jia(1,f[x]+1,x-1,-1);
			int lc=c[x][0],p=f[x];
			f[x]=0;
			c[p][1]=lc;
			if(lc)
				f[lc]=p;
		}
	}
	return 0;
}
posted @ 2018-03-06 21:53  lokiii  阅读(68)  评论(0编辑  收藏