P3721 [AH2017/HNOI2017]单旋

题目

P3721 [AH2017/HNOI2017]单旋

毒瘤的\(HNOI\),其实想清楚了不难

做法

首先这题不去考虑单纯\(splay\)的做法,单旋肯定会卡掉,不知道具体卡了多少分

这题是只用单旋,当然去手玩一下,这时候你就知道上旋最小值和最大值的子树变化规律了,线段树维护深度

然后其实就只考虑插入就好了,把\(splay\)的权值排列一下,显然相邻两个在\(splay\)里也相邻

也就是只有两种形态,每种形态能插的地方只有一个,且另一种形态这个地方不为空,枚举一下就好了

\(LCT\)维护深度也是种经典套路,但用线段树更有意思

My complete code

#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<set>
using namespace std;
typedef int LL;
const LL maxn=1e6;
inline LL Read(){
    LL x(0),f(1);char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();
    return x*f;
}
set<LL> Set;
struct node{
    LL op,a;
}q[maxn];
LL n,tot,root,Root,nod;
LL lazy[maxn],dep[maxn],lc[maxn],rc[maxn],b[maxn],son[maxn][2],fa[maxn];
inline void Pushdown(LL now){
    if(lazy[now]){
        LL val(lazy[now]); lazy[now]=0;
        if(!lc[now])lc[now]=++nod;
        if(!rc[now])rc[now]=++nod;
        lazy[lc[now]]+=val,dep[lc[now]]+=val;
        lazy[rc[now]]+=val,dep[rc[now]]+=val;
    }
}
void Add(LL &now,LL l,LL r,LL lt,LL rt,LL val){
    if(!now) now=++nod;
    if(lt<=l&&rt>=r){
        dep[now]+=val,lazy[now]+=val;
        return;
    }
    Pushdown(now);
    LL mid(l+r>>1);
    if(lt<=mid) Add(lc[now],l,mid,lt,rt,val);
    if(rt>mid) Add(rc[now],mid+1,r,lt,rt,val);
}
void Change(LL &now,LL l,LL r,LL c,LL val){
    if(!now) now=++nod;
    if(l==r){
        dep[now]=val;
        return;
    }
    Pushdown(now);
    LL mid(l+r>>1);
    if(c<=mid) Change(lc[now],l,mid,c,val);
    else Change(rc[now],mid+1,r,c,val);
}
LL Query(LL now,LL l,LL r,LL c){
    if(l==r) return dep[now];
    Pushdown(now);
    LL mid(l+r>>1);
    if(c<=mid)
        return Query(lc[now],l,mid,c);
    else
        return Query(rc[now],mid+1,r,c);
}
inline LL Insert(LL x){
    set<LL> ::iterator it=Set.insert(x).first;
    if(!root){
        Root=x; Change(root,1,tot,x,1); return 1;
    }
    if(it!=Set.begin()){
        if(!son[*--it][1]){
            son[*it][1]=x;
            fa[x]=*it;
        }
        ++it;
    }
    if(!fa[x]){
        son[*++it][0]=x;
        fa[x]=*it;
    }
    LL deep(Query(root,1,tot,fa[x])+1);
    Change(root,1,tot,x,deep);
    return deep;
}
inline LL Splaymin(){
    LL x=*Set.begin(),deep(Query(root,1,tot,x));
    if(x==Root) return 1;
    if(x+1<=fa[x]-1)
        Add(root,1,tot,x+1,fa[x]-1,-1);
    Add(root,1,tot,1,tot,1);
    son[fa[x]][0]=son[x][1];
    fa[son[x][1]]=fa[x];
    son[x][1]=Root;
    fa[Root]=x;
    Root=x;
    Change(root,1,tot,Root,1);
    return deep;
}
inline void Delmin(){
    printf("%d\n",Splaymin());
    Add(root,1,tot,1,tot,-1);
    Set.erase(Root);
    LL tmp(son[Root][1]); son[Root][1]=fa[Root]=0; Root=tmp;
    fa[Root]=0;
}
inline LL Splaymax(){
    LL x=*Set.rbegin(),deep(Query(root,1,tot,x));
    if(x==Root) return 1;
    if(fa[x]+1<=x-1)
        Add(root,1,tot,fa[x]+1,x-1,-1);
    Add(root,1,tot,1,tot,1);
    son[fa[x]][1]=son[x][0];
    fa[son[x][0]]=fa[x];
    son[x][0]=Root;
    fa[Root]=x;
    Root=x;
    Change(root,1,tot,Root,1);
    return deep;
}
inline void Delmax(){
    printf("%d\n",Splaymax());
    Add(root,1,tot,1,tot,-1);
    Set.erase(Root);
    LL tmp(son[Root][0]); son[Root][0]=fa[Root]=0; Root=tmp;
    fa[Root]=0;
}
int main(){
    n=Read();
    for(LL i=1;i<=n;++i){
        q[i].op=Read();
        if(q[i].op==1)
            b[++tot]=q[i].a=Read();
    }
    sort(b+1,b+1+tot),tot=unique(b+1,b+1+tot)-b-1;
    for(LL i=1;i<=n;++i){
        if(q[i].op==1) printf("%d\n",Insert(lower_bound(b+1,b+1+tot,q[i].a)-b));
        else if(q[i].op==2) printf("%d\n",Splaymin());
        else if(q[i].op==3) printf("%d\n",Splaymax());
        else if(q[i].op==4) Delmin();
        else Delmax();
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/y2823774827y/p/10327278.html