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;
}