[bzoj1503][NOI2004]郁闷的出纳员

题目很劲爆--OIER公司是一家大型专业化软件公司,有着数以万计的员工。作为一名出纳员,我的任务之一便是统计每位员工的工资。这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资。如果他心情好,就可能把每位员工的工资加上一个相同的量。反之,如果心情不好,就可能把他们的工资扣除一个相同的量。我真不知道除了调工资他还做什么其它事情。工资的频繁调整很让员工反感,尤其是集体扣除工资的时候,一旦某位员工发现自己的工资已经低于了合同规定的工资下界,他就会立刻气愤地离开公司,并且再也不会回来了。每位员工的工资下界都是统一规定的。每当一个人离开公司,我就要从电脑中把他的工资档案删去,同样,每当公司招聘了一位新员工,我就得为他新建一个工资档案。老板经常到我这边来询问工资情况,他并不问具体某位员工的工资情况,而是问现在工资第k多的员工拿多少工资。每当这时,我就不得不对数万个员工进行一次漫长的排序,然后告诉他答案。好了,现在你已经对我的工作了解不少了。正如你猜的那样,我想请你编一个工资统计程序。怎么样,不是很困难吧?

大概就是要支持查询k大,区间改和删点。   $n\leqslant 10^{5}$

题解:就是一道很裸的平衡树呗。然后我突然决定用这道题学学treap,然后就莫名调了好久..

#include<iostream>
#include<cstdio>
#define MN 100000
#define INF 0x7FFFFFFF
using namespace std;
inline int read()
{
    int x = 0 , f = 1; char ch = getchar();
    while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
    while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
    return x * f;
}
inline int Ran()
{
    static int x=23333;
    x^=(x<<13);x^=(x>>17);x^=(x<<5);return x;
}

char op[5];
int fa[MN+5],c[MN+5][2],size[MN+5],val[MN+5],nn[MN+5],n,K,s[MN+5],cnt=0,rt=0,ans=0;

inline void update(int x){size[x]=size[c[x][0]]+size[c[x][1]]+1;}

void pushdown(int x)
{
    int l=c[x][0],r=c[x][1];
    val[l]+=val[x];val[r]+=val[x];
    nn[l]+=val[x];nn[r]+=val[x];
    val[x]=0;
}

void rotate(int x)
{
    int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1;
    c[z][c[z][1]==y]=x; if(y==rt)rt=x;
    fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
    c[y][l]=c[x][r];c[x][r]=y;
    update(y);update(x);
}

void ins(int x,int rk)
{
    // if(++tms>MN*100)exit(0);
    if(!x)rt=++cnt; else
    {
        int t=(rk>nn[x]);pushdown(x);++size[x];
        while(c[x][t]) {x=c[x][t];++size[x];pushdown(x);t=rk>nn[x];}
        c[x][t]=++cnt;fa[cnt]=x;
    }
    size[cnt]=1;s[cnt]=Ran();nn[cnt]=rk;
    while(fa[cnt]&&s[cnt]>s[fa[cnt]])rotate(cnt);
}

int find(int x,int rk)
{
    if(!x)return -1;
    if(val[x]) pushdown(x);
    int l=size[c[x][0]];
    if(l+1==rk)return x;
    if(l+1<rk) return find(c[x][1],rk-l-1);
    return find(c[x][0],rk);
}

void del(int x)
{
    c[fa[x]][0]=c[x][1];fa[c[x][1]]=fa[x];if(x==rt) rt=c[x][1];
    while(x=fa[x])update(x);
}

int main()
{
    n=read();K=read();s[0]=-INF;
    for(int i=1;i<=n;i++)
    {
        scanf("%s",op);int x=read();
        if(op[0]=='I') {if(x>=K)ins(rt,x);}
        if(op[0]=='S') {nn[rt]-=x;val[rt]-=x;while((x=find(rt,1))>0&&nn[x]<K) del(x),++ans;}
        if(op[0]=='F') {printf("%d\n",(x=find(rt,size[rt]-x+1))==-1?-1:nn[x]);}
        if(op[0]=='A') {nn[rt]+=x;val[rt]+=x;}
    }
    printf("%d\n",ans);
    return 0;
}

 

posted @ 2017-03-28 08:48  FallDream  阅读(198)  评论(0编辑  收藏  举报