【codevs1286】【BZOJ1503】郁闷的出纳员,splay练习

传送门1
传送门2
写在前面:代码一长,细节问题就多了起来,还是需要熟练啊
思路:插入,删除,查第k大的splay,再加一个改值函数,因为改动工资的操作很少(才100),所以直接暴力从根开始往下改,小于工资下限就入队,最后把队里的元素删除就行
注意:一开始的工资就小于下限的人不会进公司,但也不计入离开公司的人数,切记!
代码:

#include<bits/stdc++.h>
using namespace std;
int root,n,minn,tot,ans,x;
char ch;
queue<int> q;
struct os
{
    int occ,data,fa,sz,ch[2];
}a[100100];
void ct(int now)
{
    a[now].sz=a[now].occ+a[a[now].ch[0]].sz+a[a[now].ch[1]].sz;
}
void made(int x)
{
    a[++tot].data=x;
    a[tot].occ=a[tot].sz=1;
}
void rorate(int now,bool x)
{
    int pa=a[now].fa;
    a[a[now].fa].ch[x^1]=a[now].ch[x];
    if (a[now].ch[x])a[a[now].ch[x]].fa=pa;
    a[now].fa=a[pa].fa;
    if (a[pa].fa) 
    {
        if (a[a[pa].fa].ch[0]==pa) a[a[pa].fa].ch[0]=now;
        else a[a[pa].fa].ch[1]=now;
    }
    a[pa].fa=now;
    a[now].ch[x]=pa;
    ct(pa);
    ct(now);
}
void splay(int now,int goal)
{
    int pa;
    while (a[now].fa!=goal)
    {
        pa=a[now].fa;
        if (a[pa].fa==goal)
        {
            if (a[pa].ch[0]==now) rorate(now,1);
            else rorate(now,0);
        }
        else if (a[a[pa].fa].ch[0]==pa)
        {
            if (a[pa].ch[0]==now) rorate(pa,1);
            else rorate(now,0);
            rorate(now,1);
        }
        else
        {
            if (a[pa].ch[1]==now) rorate(pa,0);
            else rorate(now,1);
            rorate(now,0);
        }
    }
    if (!goal) root=now; 
}
void insert(int x)
{
    if (!root) {made(x);root=tot;return;}
    int now=root,flag=1;
    while (flag)
    {
        a[now].sz++;
        if (a[now].data==x){a[now].occ++;splay(now,0);return;}
        else if (a[now].data>x)
        {
            if (!a[now].ch[0]) made(x),a[now].ch[0]=tot,a[tot].fa=now,flag=0;
            else now=a[now].ch[0];
        }
        else
        {
            if (!a[now].ch[1]) made(x),a[now].ch[1]=tot,a[tot].fa=now,flag=0;
            else now=a[now].ch[1];
        }
    }
    splay(tot,0);
}
void update(int now,int x)
{
    if (!now) return;
    a[now].data+=x;
    if (a[now].data<minn) q.push(now);
    update(a[now].ch[0],x);
    update(a[now].ch[1],x);
}
int Kth(int k)
{
    if (k<=0) return 0;
    int now=root;
    while (now)
    {
        if (a[a[now].ch[1]].sz<k&&a[a[now].ch[1]].sz+a[now].occ>=k) break;
        if (a[a[now].ch[1]].sz>=k) now=a[now].ch[1];
        else k-=(a[a[now].ch[1]].sz+a[now].occ),now=a[now].ch[0];
    }
    if (now) splay(now,0);
    return now;
}
int find_max(int now)
{
    if (!now) return 0;
    while (now)
    {
        if (!a[now].ch[1]) return now;
        else now=a[now].ch[1];
    }
}
bool del(int now)
{
    if (!now) return 0;
    splay(now,0);
    if (!a[now].ch[0]&&!a[now].ch[1]) root=0;
    else if (!a[now].ch[1])
    {
        root=a[now].ch[0];
        a[a[now].ch[0]].fa=0;
    }
    else if (!a[now].ch[0])
    {
        root=a[now].ch[1];
        a[a[now].ch[1]].fa=0;
    }
    else
    {
        splay(find_max(a[now].ch[0]),root);
        root=a[now].ch[0];
        a[a[now].ch[0]].fa=0;
        a[a[now].ch[1]].fa=a[now].ch[0];
        a[a[now].ch[0]].ch[1]=a[now].ch[1];
        ct(a[now].ch[0]);
    }
    return 1;
}
main()
{
    scanf("%d%d",&n,&minn);
    a[0].data=-1;
    while (n--)
    {
        ch=getchar();
        while (ch!='I'&&ch!='A'&&ch!='S'&&ch!='F') ch=getchar();
        scanf("%d",&x);
        if (ch=='I')
        {
            if (x>=minn) insert(x);
        }
        else if (ch=='A') update(root,x);
        else if (ch=='S') 
        {
            update(root,-x);
            while (!q.empty())
            ans+=a[q.front()].occ,
            del(q.front()),
            q.pop();
        }
        else printf("%d\n",a[Kth(x)].data);
    }
    printf("%d",ans);
}

你可能感兴趣的:(【codevs1286】【BZOJ1503】郁闷的出纳员,splay练习)