BZOJ[NOI2004]郁闷的出纳员 | Splay板子题

题目:

洛谷也能评测....还有我wa了10多次的记录233


题解:

不要想得太复杂,搞一个全局变量记录一下工资的改变量Delta,这样可以等询问的时候就输出val+Delta,然后插入的时候插入x-Delta

不要想会不会有员工工资一样,直接插入就好,这样省不少代码量.

对于降工资操作,插入一个min-Delta节点,ans+=左子树大小,右儿子作为新的根节点

直接走的员工不要算ans

#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 200010
#define which(x) (ls[fa[(x)]]==x)
using namespace std;
int sz[N],ls[N],rs[N],val[N],fa[N],n,lim,k,tot,delta,ans,root;
char s[N];
void Pushup(int x){sz[x]=1+sz[ls[x]]+sz[rs[x]];} 
void Rotate(int u)
{
    int v=fa[u],w=fa[v],b=which(u)?rs[u]:ls[u];
    if (w) which(v)?ls[w]=u:rs[w]=u;
    which(u)?(ls[v]=b,rs[u]=v):(rs[v]=b,ls[u]=v);
    fa[u]=w,fa[v]=u;
    if (b) fa[b]=v;
    Pushup(v);Pushup(u);
}
void Splay(int u)
{
    while (fa[u])
    {
        if (fa[fa[u]])
            if (which(u)==which(fa[u])) Rotate(fa[u]);
            else Rotate(u);
        Rotate(u);
    }
    root=u;
}
void Insert(int x)
{
    int cur=root,v=0,dir;
    while (cur)
    {
        if (val[v=cur]>=x) cur=ls[cur],dir=0;
        else cur=rs[cur],dir=1;
        sz[v]++;
    }
    val[++tot]=x,fa[tot]=v,sz[tot]=1;
    if (v) dir==0?ls[v]=tot:rs[v]=tot; 
    Splay(tot); 
}
int getkth(int k)
{
    int cur=root;
    while (cur)
    {
        if (sz[ls[cur]]>=k) cur=ls[cur];
        else if (sz[ls[cur]]+1>=k) return val[cur];
            else k-=sz[ls[cur]]+1,cur=rs[cur];
    }
    return val[cur];
}
void Delete()
{
    Insert(lim-delta);
    ans+=sz[ls[root]];
      root=rs[root],fa[root]=0;
}
int main()
{
    scanf("%d%d",&n,&lim);
    for (int i=1;i<=n;i++)
    {
    scanf("%s%d",s+1,&k);
    if (s[1]=='I')
        if (k>=lim) Insert(k-delta);
    if (s[1]=='A') delta+=k;  
    if (s[1]=='S') delta-=k,Delete();
    if (s[1]=='F')
        if (sz[root]<k || root==0) puts("-1");
        else printf("%d\n",getkth(sz[root]-k+1)+delta);
    }
    printf("%d",ans);
    return 0;
}

 

posted @ 2017-12-26 23:01  MSPqwq  阅读(215)  评论(0编辑  收藏  举报