bzoj 1503 [NOI2004]郁闷的出纳员 平衡树(treap/Splay)

原创 2015年11月21日 12:03:06

Description

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

Input

Output

输出文件的行数为F命令的条数加一。对于每条F命令,你的程序要输出一行,仅包含一个整数,为当前工资第k多的员工所拿的工资数,如果k大于目前员工的数目,则输出-1。输出文件的最后一行包含一个整数,为离开公司的员工的总数。

Sample Input

9 10
I 60
I 70
S 50
F 2
I 30
S 15
A 5
F 1
F 2

Sample Output

10
20
-1
2

HINT

I命令的条数不超过100000 A命令和S命令的总条数不超过100 F命令的条数不超过100000 每次工资调整的调整量不超过1000 新员工的工资不超过100000

Key To Problem

treap和splay都可以搞

Code

//treap
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define N 100010
using namespace std;
struct node
{
    int l,r,v,size,rnd,w;
};
node a[N];
int n,size,root,ans,min_s,delet,sum;
char s[10];

void updata(int k)
{
    a[k].size=a[a[k].l].size+a[a[k].r].size+1;
}

void lturn(int &k)
{
    int t=a[k].r;
    a[k].r=a[t].l,a[t].l=k;
    a[t].size=a[k].size,updata(k),k=t;
}

void rturn(int &k)
{
    int t=a[k].l;
    a[k].l=a[t].r,a[t].r=k;
    a[t].size=a[k].size,updata(k),k=t;
}

void insert(int &k,int x)
{
    if(k==0)
    {
        k=++size;
        a[k].v=x,a[k].size=a[k].w=1,a[k].rnd=rand();
        return ;
    }
    a[k].size++;
    if(x>a[k].v)
    {
        insert(a[k].r,x);
        if(a[a[k].r].rnd<a[k].rnd)lturn(k);
    }else
    {
        insert(a[k].l,x);
        if(a[a[k].l].rnd<a[k].rnd)rturn(k);
    }
}

int del(int &k,int x)
{
    int t=0;
    if(k==0)return 0;
    if(x>a[k].v)
    {
        t=a[a[k].l].size+1;
        k=a[k].r;
        return t+del(k,x);
    }else
    {
        t=del(a[k].l,x);
        a[k].size-=t;
        return t;
    }
}

int query(int k,int x)
{
    if(k==0)return 0;
    if(a[a[k].l].size+1==x)return a[k].v+delet;
    if(x<a[a[k].l].size+1)return query(a[k].l,x);
    else return query(a[k].r,x-a[a[k].l].size-1);
}

int main()
{
//  freopen("cashier.in","r",stdin);
//  freopen("cashier.out","w",stdout);
    cin>>n>>min_s;
    while(n--)
    {
        int x;
        scanf("%s%d",s+1,&x);
        if(s[1]=='I'&&x>=min_s)insert(root,x-delet);
        else if(s[1]=='A')delet+=x;
        else if(s[1]=='S')
        {
            delet-=x;
            sum+=del(root,min_s-delet);
        }
        else if(s[1]=='F')
        {
            if(x>a[root].size)puts("-1");
            else printf("%d\n",query(root,a[root].size-x+1));
        }
    }
    printf("%d\n",sum);
    return 0;
}
//splay
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 100010
#define ls(x) tr[x].l
#define rs(x) tr[x].r
#define fa(x) tr[x].fa
using namespace std;
struct node
{
    int l,r,fa,size,v;
};
node tr[N];
int n,m,tot,root,delta,sum;

void PushUp(int x)
{
    tr[x].size=tr[ls(x)].size+tr[rs(x)].size+1;
}

void zig(int x)
{
    int y=fa(x);
    int z=fa(y);
    if(y==ls(z))ls(z)=x;
    else rs(z)=x;
    fa(x)=z,ls(y)=rs(x),fa(y)=x,fa(rs(x))=y,rs(x)=y;
    PushUp(y),PushUp(x);
    if(y==root)root=x;
}

void zag(int x)
{
    int y=fa(x);
    int z=fa(y);
    if(y==ls(z))ls(z)=x;
    else rs(z)=x;
    fa(x)=z,rs(y)=ls(x),fa(y)=x,fa(ls(x))=y,ls(x)=y;
    PushUp(y),PushUp(x);
    if(y==root)root=x;
}

void Splay(int x,int d)
{
    while(fa(x)!=d)
    {
        if(ls(fa(x))==x)zig(x);
        else zag(x);
    }
}

void insert(int x)
{
    if(!root)
    {
        root=++tot;
        tr[tot].v=x,tr[tot].size=1;
        return ;
    }
    int p=root,z;
    while(p)
    {
        z=p;
        tr[p].size++;
        if(x<tr[p].v)p=ls(p);
        else p=rs(p);
    }
    if(x<tr[z].v)ls(z)=++tot;
    else rs(z)=++tot;
    tr[tot].v=x,tr[tot].size=1,fa(tot)=z;
    Splay(tot,0);
}

int del(int &x,int f)
{
    if(!x)return 0;
    int k;
    if(tr[x].v+delta<m)
    {
        k=del(rs(x),x)+tr[ls(x)].size+1;
        tr[rs(x)].size=tr[x].size-k;
        x=rs(x),fa(x)=f;
    }else
    {
        k=del(ls(x),x);
        tr[x].size-=k;
    }
    return k;
}

int query(int x,int k)
{
    if(k<=tr[rs(x)].size)return query(rs(x),k);
    if(k==tr[rs(x)].size+1)return tr[x].v;
    return query(ls(x),k-tr[rs(x)].size-1);
}

int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        char s[10];
        int x;
        scanf("%s%d",s,&x);
        if(s[0]=='I'&&x>=m)insert(x-delta);
        else if(s[0]=='A')delta+=x;
        else if(s[0]=='S')delta-=x,sum+=del(root,0);
        else if(s[0]=='F'&&x>tr[root].size)puts("-1");
        else if(s[0]=='F')printf("%d\n",query(root,x)+delta);
    }
    cout<<sum<<endl;
    return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

BZOJ1503 NOI2004 郁闷的出纳员 题解&代码

题意太傻不多解释= =就是维护一个档案队列,按节点val建树思路: 从query操作(命令F)可以看出,这棵树的顺序核心在于value而不是一般的维护队列,这样的话相同value的节点显而易见地应该...

BZOJ1503——郁闷的出纳员

1、题目大意:一道treap题,支持插入,询问第K大,还有全体修改+上一个值,如果某个点值小于x,那么就删除这个点 插入100000次,询问100000次,修改100次。。最后输出删了多少个点 2...

[BZOJ1503][NOI2004]郁闷的出纳员(平衡树splay)

海水是咸的,因为它包含了人世所有的泪水;泪水是咸的,因为它承载了太多的欢乐和苦悲。...

【Splay|Treap】poj3580 SuperMemo && bzoj1503 [noi2004]郁闷的出纳员

splay真的是一种十分耐吃的植物。啃了三四天终于啃熟了 orz  当然现在还仅限于模板题T T 很多东西还是要努力啊!!! debug的过程真的是十分的艰辛orz 找了毕克大魔王他说叫我再想想QAQ...

BZOJ 1503 [NOI2004] 郁闷的出纳员 treap

题意: 链接 方法: treap 解析: 这是本蒟蒻的第二道treap题,第二遍写的时候update,左旋右旋,插入函数都可以大概写出来了(还是得练啊),然而del  函数却被虐了,自己也想...
  • wzq_QwQ
  • wzq_QwQ
  • 2015年03月20日 13:44
  • 1819

[BZOJ1503]NOI2004 郁闷的出纳员|splay

这题方法应该有很多,什么树状数组线段树都能搞。。 用splay的话就是维护工资序列咯,但是每次修改都逐个修改的话肯定会T掉,注意到修改是整体修改,所以只要维护一个相对的修改值,然后修改的时候要考虑上...

【BZOJ1503】【NOI2004】郁闷的出纳员,Splay,调得我整个人都不好了。

NOI2004郁闷的出纳员
  • Vmurder
  • Vmurder
  • 2014年10月03日 17:54
  • 1093

【BZOJ1503】[NOI2004]郁闷的出纳员【Splay】

【题目链接】 写的心累。。 将A操作看为降低工资底线,将S操作看为升高工资底线。那么这样就不用标记下传了。 另外一开始要加一个inf节点,不能再加个-inf节点,因为会被删掉... 写删除的时候...

【splay】【树状数组】 BZOJ 1503 [NOI2004]郁闷的出纳员

/************************************************************** Problem: 1503 User: 70403523...

BZOJ 1503 [NOI2004] :郁闷的出纳员(Splay)

Description OIER 公司是一家大型专业化软件公司,有着数以万计的员工。作为一名出纳员,我的任务之一便是统计每位员工的工资。这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:bzoj 1503 [NOI2004]郁闷的出纳员 平衡树(treap/Splay)
举报原因:
原因补充:

(最多只允许输入30个字)