bzoj 1503 [NOI2004]鬱悶的出納員 平衡樹(treap/Splay)

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章