Splay练习2——P1486 [NOI2004]郁闷的出纳员

蒟蒻的垂死挣扎

这题就是一道splay模板题啊。

对于boss调整工资,直接在外面记一个变量now统一处理,每次新插入的节点键值为k-now,而每次降低工资的时候我们就将工资标准mmin-now作为真正的标准,找到前驱,转到根,直接删左子树就行,具体细节自己想咯。

// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
#include<queue>
#define RG register
#define N 500100
#define ls s[x][0]
#define rs s[x][1]
#define ll long long
#define ld long double
using namespace std;

inline int read(){
  RG int x=0,o=1; RG char ch=getchar();
  while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
  if(ch=='-') o=-1,ch=getchar();
  while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
  return x*o;
}

int w[N],siz[N],num[N],fa[N],s[N][2],tot,root;

inline void Pushup(RG int x) { siz[x]=siz[ls]+siz[rs]+num[x]; }

inline void Rotate(RG int x){
    RG int y=fa[x],z=fa[y],k=s[y][1]==x,ot=s[x][k^1];
    s[z][s[z][1]==y]=x,s[y][k]=ot,s[x][k^1]=y;
    fa[x]=z,fa[y]=x,fa[ot]=y; Pushup(y),Pushup(x);
}

inline void Splay(RG int x,RG int goal){
    while(fa[x]!=goal){
        RG int y=fa[x],z=fa[y];
        if(z!=goal) (s[y][0]==x)^(s[z][0]==y)?Rotate(x):Rotate(y);
        Rotate(x);
    }   if(!goal) root=x;
}

inline void Find(RG int x){
    RG int u=root;
    while(s[u][x>w[u]]&&w[u]!=x) u=s[u][x>w[u]];
    Splay(u,0);
}

inline int Next(RG int x,RG int op){
    Find(x);  RG int u=root;
    if(w[u]>=x&&op)  return u;
    if(w[u]<=x&&!op) return u;
    u=s[u][op];
    while(s[u][op^1]) u=s[u][op^1];
    return u;
}

inline void Insert(RG int x){
    RG int u=root,fat=0;
    while(u&&x!=w[u]) fat=u,u=s[u][x>w[u]];
    if(u) ++num[u];
    else{
        u=++tot; if(fat) s[fat][x>w[fat]]=u;
        num[u]=siz[u]=1,fa[u]=fat,w[u]=x;
    } Splay(u,0);
}

inline int Kth(RG int x){
    RG int u=root;
    if(x>siz[u]) return -1;
    if(x<=0) return -1;
    while(233){
        if(x>siz[s[u][0]]+num[u]) x-=siz[s[u][0]]+num[u],u=s[u][1];
        else if(x<=siz[s[u][0]]) u=s[u][0];
        else return w[u];
    }
}

int main(){
    RG int n=read(),mmin=read();
    RG int now=0,sum=0,peo=0; Insert(2147483647);
    for(RG int i=1;i<=n;++i){
        RG char op=getchar(); while(op!='I'&&op!='A'&&op!='S'&&op!='F') op=getchar();
        RG int x=read();
        if(op=='I'){
            if(x<mmin) continue ;
            Insert(x-now),++peo;
        }
        if(op=='A') now+=x;
        if(op=='S') now-=x;
        if(op=='S'){
            RG int st=mmin-now;
            RG int gg=Next(st,1); Splay(gg,0);
            sum+=siz[s[root][0]],peo-=siz[s[root][0]];
            siz[s[root][0]]=s[root][0]=s[root][0]=siz[0]=0;
            Pushup(root);
        }
        if(op=='F') {
            //		cout<<peo<<' ';
            int ans=Kth(peo-x+1);
//			if(abs(ans)==2147483647) ans=-1;
            if(ans!=-1) ans+=now;
            printf("%d\n",ans);
        }

//		for(RG int i=1;i<=tot;++i) cout<<w[i]<<' ';cout<<endl<<now<<endl;
        
    } printf("%d\n",sum);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值