BZOJ4825: [Hnoi2017]单旋

BZOJ4825

想到了就是打码题。。然而我考场上就没想出来维护深度QAQ,还加起来花了四个小时去打一个错的。。最后一题还有四十分也没去打。。气死了。。(还是太水了,几个月以后就是NOI送分宝宝。。)

维护原树的形状,将当前树中值插入某可维护最大最小值的数据结构中(本蒟蒻用的splay),然后再用一个数据结构维护一下每个节点的深度。
发现操作2对深度的影响就是将最小值深度变为1,除了最小值和其右子树外全部深度加一,操作3类似。
操作4就是将最小值右子树深度减一,然后删除该点。操作5类似。
(细节地方好多啊!!今天莫名其妙还不让我对拍。。手动对拍几十组QAQ,调一组改一组累死了TAT)
代码打的巨丑啊。。用STL会好打很多吧,然而蒟蒻不会QAQ

【代码】

#include <cstdio>
#include <iostream>
#include <queue>
#include <algorithm>
#include <cmath>
#include <cstring>
#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(k<x)
    {
        Pre=k;
        Get_Pre(x,son[k][1]);
    }
    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(x<Last) Next=Last,Get_Pre(x,rt);
        else 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(x<k) Insert(x,son[k][0],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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值