BZOJ4825
想到了就是打码题。。然而我考场上就没想出来维护深度QAQ,还加起来花了四个小时去打一个错的。。最后一题还有四十分也没去打。。气死了。。(还是太水了,几个月以后就是NOI送分宝宝。。)
维护原树的形状,将当前树中值插入某可维护最大最小值的数据结构中(本蒟蒻用的splay),然后再用一个数据结构维护一下每个节点的深度。
发现操作2对深度的影响就是将最小值深度变为1,除了最小值和其右子树外全部深度加一,操作3类似。
操作4就是将最小值右子树深度减一,然后删除该点。操作5类似。
(细节地方好多啊!!今天莫名其妙还不让我对拍。。手动对拍几十组QAQ,调一组改一组累死了TAT)
代码打的巨丑啊。。用STL会好打很多吧,然而蒟蒻不会QAQ
#include
#include
#include
#include
#include
#include
#define N 100005
#define M 1000005
using namespace std;
typedef unsigned long long ull;
const ull base=31;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
int m,n,rt,Trt,sum,Next,Pre;
int F[N],A[N],Hash[N];
int fa[N],son[N][2],Tfa[N],Deep[N],Tson[N][2];
class Seg_Tree{
public:
int l,r,deep,tag;
}e[N<<2];
void Build(int p,int l,int r)
{
e[p].l=l,e[p].r=r;
if(l==r) return;
int mid=l+r>>1;
Build(p<<1,l,mid);Build(p<<1|1,mid+1,r);
}
int Find(int x)
{
int l=1,r=n,rtn;
while(l<=r)
{
int mid=l+r>>1;
if(Hash[mid]>=x) rtn=mid,r=mid-1;
else l=mid+1;
}
return rtn;
}
void pushdown(int p)
{
e[p<<1].tag+=e[p].tag;e[p<<1|1].tag+=e[p].tag;
e[p<<1].deep+=e[p].tag;e[p<<1|1].deep+=e[p].tag;
e[p].tag=0;
}
void Update(int p,int y,int z)
{
int l=e[p].l,r=e[p].r,mid=l+r>>1;
if(l==r)
{
e[p].deep=z;
return;
}
if(e[p].tag) pushdown(p);
if(y<=mid) Update(p<<1,y,z);
else Update(p<<1|1,y,z);
}
void Rotate(int x,int &k)
{
int y=fa[x],z=fa[y],l,r;
l=son[y][1]==x,r=l^1;
if(y==k) k=x;
else son[z][son[z][1]==y]=x;
fa[x]=z;fa[y]=x;fa[son[x][r]]=y;
son[y][l]=son[x][r];son[x][r]=y;
}
void Splay(int x,int &k)
{
while(x!=k)
{
int y=fa[x],z=fa[y];
if(y!=k)
{
if(son[z][0]==y^son[y][0]==x) Rotate(x,k);
else Rotate(y,k);
}
Rotate(x,k);
}
}
int Find_Min()
{
int rtn=rt;
while(son[rtn][0]) rtn=son[rtn][0];
return rtn;
}
int Find_Max()
{
int rtn=rt;
while(son[rtn][1]) rtn=son[rtn][1];
return rtn;
}
int Query(int p,int x)
{
if(!x) return 0;
int l=e[p].l,r=e[p].r,mid=l+r>>1;
if(l==r)
return e[p].deep;
if(e[p].tag) pushdown(p);
if(x<=mid) return Query(p<<1,x);
return Query(p<<1|1,x);
}
void Get_Pre(int x,int k)
{
if(!k) return;
if(k1]);
}
else Get_Pre(x,son[k][0]);
}
void Get_Next(int x,int k)
{
if(!k) return;
if(k>x)
{
Next=k;
Get_Next(x,son[k][0]);
}
else Get_Next(x,son[k][1]);
}
void Insert(int x,int &k,int Last)
{
if(!k)
{
Pre=Next=0;
k=x;fa[x]=Last;if(xelse Pre=Last,Get_Next(x,rt);
int dn=Query(1,Next),dp=Query(1,Pre);
if(dn>dp) Tfa[x]=Next,Tson[Next][0]=x;
else Tfa[x]=Pre,Tson[Pre][1]=x;
printf("%d\n",max(dn,dp)+1);
Update(1,x,max(dn,dp)+1);Splay(x,rt);return;
}
if(x0],k);
else Insert(x,son[k][1],k);
}
void update(int p,int x,int y,int z)
{
if(x>y) return;
int l=e[p].l,r=e[p].r,mid=l+r>>1;
if(x==l&&y==r)
{
e[p].deep+=z;
e[p].tag+=z;return;
}
if(e[p].tag) pushdown(p);
if(y<=mid) update(p<<1,x,y,z);
else if(x>mid) update(p<<1|1,x,y,z);
else update(p<<1,x,mid,z),update(p<<1|1,mid+1,y,z);
}
void Solve_Min()
{
int x=Find_Min();
printf("%d\n",Query(1,x));
int k=Trt,y=Tfa[x],z=Tson[x][1];
if(k==x) return;
if(y) update(1,y,n,1);Update(1,x,1);
Tson[y][0]=z;Tfa[z]=y;Tfa[x]=0;
Tson[x][1]=k,Tfa[k]=x;Trt=x;
Splay(x,rt);
}
void Solve_Max()
{
int x=Find_Max();
printf("%d\n",Query(1,x));
int k=Trt,y=Tfa[x],z=Tson[x][0];
if(k==x) return;
if(y) update(1,1,y,1);Update(1,x,1);
Tson[y][1]=z;Tfa[z]=y;Tfa[x]=0;
Tson[x][0]=k,Tfa[k]=x;Trt=x;
Splay(x,rt);
}
void Work_Min()
{
int x=Find_Min();
printf("%d\n",Query(1,x));
int y=Tfa[x],z=Tson[x][1];
if(y) update(1,x+1,y-1,-1);
else
{
Trt=z;
if(z) update(1,x+1,n,-1);
}
Tfa[z]=y;Tson[x][1]=0;Tson[y][0]=z;
Splay(x,rt);
rt=son[x][1];son[x][1]=fa[son[x][1]]=0;
}
void Work_Max()
{
int x=Find_Max();
printf("%d\n",Query(1,x));
int y=Tfa[x],z=Tson[x][0];
if(y) update(1,y+1,x-1,-1);
else
{
Trt=z;
if(z) update(1,1,x-1,-1);
}
Tfa[z]=y;Tson[x][0]=0;Tson[y][1]=z;
Splay(x,rt);
rt=son[x][0];son[x][0]=fa[son[x][0]]=0;
}
int main()
{
m=read();
for(int i=1;i<=m;i++)
{
F[i]=read();
if(F[i]==1) Hash[++n]=A[i]=read();
}
sort(Hash+1,Hash+1+n);
for(int i=1;i<=m;i++)
if(F[i]==1) A[i]=Find(A[i]);
Build(1,1,n);
for(int i=1;i<=m;i++)
{
if(F[i]==1)
{
Insert(A[i],rt,0),sum++;
if(sum==1) Trt=A[i];
}
else if(F[i]==2) Solve_Min();
else if(F[i]==3) Solve_Max();
else if(F[i]==4) Work_Min(),sum--;
else Work_Max(),sum--;
}
return 0;
}