BZOJ 1503 郁闷的出纳员

Posted on 2016-03-23 20:22  ziliuziliu  阅读(274)  评论(0编辑  收藏  举报

一个很巧的地方是:既然是所有的人加减工资,那么可以直接在全局上修改。

然而直接用value+delta这样的形式是不对的,因为后来的人并没有经受前面的考验。

所以我们要在splay里面保存value-delta,然后在输出权值的时候加上目前的delta即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 100500
#define inf 99999999
using namespace std;
int delta=0,n,minn,tree[maxn][3],w[maxn],fath[maxn],size[maxn],value[maxn];
int x,ans=0,tot=0,re,root=0;
char type[5];
void pushup(int now)
{
    int ls=tree[now][1],rs=tree[now][2];
    size[now]=size[ls]+size[rs]+w[now];
}
int insert(int x,int now,int father)
{
    int regis;
    int ls=tree[now][1],rs=tree[now][2];
    if (now==0)
    {
        now=++tot;
        fath[now]=father;
        size[now]=1;w[now]=1;
        if (x<value[father]) tree[father][1]=now;
        else tree[father][2]=now;
        value[now]=x;
        return now;    
    }
    if (x<value[now]) regis=insert(x,ls,now);
    else if (x>value[now]) regis=insert(x,rs,now);
    else {size[now]++;w[now]++;regis=now;}
    pushup(now);
    return regis;
}
void rotate(int x,int &k)
{
    int y=fath[x],z=fath[y],l,r;
    if (tree[y][1]==x) l=1;else l=2;
    r=3-l;
    if (y==k) k=x;
    else
    {
        if (tree[z][1]==y) tree[z][1]=x;
        else tree[z][2]=x;
    }
    fath[x]=z;fath[y]=x;fath[tree[x][r]]=y;
    tree[y][l]=tree[x][r];tree[x][r]=y;
    pushup(y);pushup(x);
}
void splay(int x,int &k)
{
    while (x!=k)
    {
        int y=fath[x],z=fath[y];
        if (y!=k)
        {
            if ((tree[y][1]==x)^(tree[z][1]==y)) rotate(x,k);
            else rotate(y,k);
        }
        rotate(x,k);
    }
}
void pre(int x,int now)
{
    if (now==0) return;
    int ls=tree[now][1],rs=tree[now][2];
    if (value[now]<x)
    {
        re=now;
        pre(x,rs);
    }
    else pre(x,ls);
}
int rank(int x,int now)
{
    if (now==0) return 0;
    int ls=tree[now][1],rs=tree[now][2];
    if (x<=size[rs]) return rank(x,rs);
    else if (x>size[rs]+w[now]) return rank(x-size[rs]-w[now],ls);
    else return value[now];
}
void work1()
{
    int regis;
    scanf("%d",&x);
    if ((tot==0) || (root==0)) {tot++;root=tot;value[root]=x-delta;size[root]=1;w[root]=1;}
    else if (x>=minn) {regis=insert(x-delta,root,root);splay(regis,root);}
}
void work2()
{
    scanf("%d",&x);
    delta=delta+x; 
}
void work3()
{
    scanf("%d",&x);
    delta=delta-x;
    pre(minn-delta,root);
    if (re!=0)
    { 
        splay(re,root);
        ans=ans+size[tree[root][1]]+w[root];
        root=tree[root][2];
    }
    re=0;
}
void work4()
{
    int regis;
    scanf("%d",&x);
    regis=rank(x,root);
    if (regis==0) printf("-1\n");
    else printf("%d\n",regis+delta);
}
int main()
{
    scanf("%d%d",&n,&minn);
    for (int i=1;i<=n;i++)
    {
        scanf("%s",type);
        if (type[0]=='I') work1();
        else if (type[0]=='A') work2();
        else if (type[0]=='S') work3();
        else work4();
    }
    printf("%d\n",ans);
    return 0;
}