[伸展树]codevs1286 郁闷的出纳员

本文介绍了一个关于工资管理和调整的问题解决方法,通过使用特殊的二叉搜索树数据结构来实现高效的操作,包括添加员工、调整工资、删除员工等功能,并提供了一段完整的C++代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

codevs1286 郁闷的出纳员

主要是删人的问题
找工资下界,找得到的话就把他的左子树删掉删掉!
如果没有人刚好在工资下界
那么….
找工资下界的后继,把后继的左子树删掉删掉!
如果后继为零,也就是说没有人的工资比下界还要大,把整棵树删掉
坑点:
建立工作档案的时候工资就低于工资下界的人不算辞职的人

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
int len,root;
struct node
{
    int n,c,f,d,son[2]; 
} tr[100010];
void update(int x)
{
    int lc=tr[x].son[0],rc=tr[x].son[1];
    tr[x].c=tr[x].n+tr[lc].c+tr[rc].c;
}
void add(int d,int f)
{
    len++;
    tr[len].d=d;tr[len].f=f;tr[len].c=1;tr[len].n=1;
    tr[len].son[1]=tr[len].son[0]=0;
    if (d<tr[f].d) tr[f].son[0]=len; else tr[f].son[1]=len; 
}
int findip(int d)
{
    int x=root;
    while (tr[x].d!=d)
    {
        if (d<tr[x].d)
        {
            if (tr[x].son[0]==0) break;
            else x=tr[x].son[0]; 
        }
        else
        {
            if (tr[x].son[1]==0) break;
            else x=tr[x].son[1];
        }
    }
    return x;
}
void rotate(int x,int w)
{
    int f=tr[x].f,ff=tr[f].f;
    int r,R;
    r=tr[x].son[w];R=f;
    tr[R].son[1-w]=r;
    if (r!=0) tr[r].f=R;
    r=x;R=ff;
    tr[r].f=R;
    if (f==tr[ff].son[0]) tr[R].son[0]=r;
    else tr[R].son[1]=r;
    r=f;R=x;
    tr[r].f=R;
    tr[R].son[w]=r;
    update(f);
    update(x);
}
void splay(int x,int rt)
{
    while (tr[x].f!=rt)
    {
        int f=tr[x].f,ff=tr[f].f;
        if (rt==ff)
        {
            if (tr[f].son[0]==x) rotate(x,1);
            else rotate(x,0);
        }
        else 
        {
            if (tr[f].son[0]==x&&tr[ff].son[0]==f) {rotate(f,1);rotate(x,1);}
            else if (tr[f].son[1]==x&&tr[ff].son[1]==f) {rotate(f,0);rotate(x,0);}
            else if (tr[f].son[0]==x&&tr[ff].son[1]==f) {rotate(x,1);rotate(x,0);}
            else if (tr[f].son[1]==x&&tr[ff].son[0]==f) {rotate(x,0);rotate(x,1);}
        }
    }
    if (rt==0) root=x;
}
void ins(int d)
{
    if (root==0)
    {
        add(d,len);
        root=len;
        return ;
    }
    else 
    {
        int x=findip(d);
        if (d==tr[x].d)
        {
            tr[x].n++;
            update(x);
            splay(x,0);
        }
        else 
        {
            add(d,x);
            update(x);
            splay(len,0);

        }
    }
}
void del(int d)
{
    int x=findip(d);
    splay(x,0);
    if (tr[x].d!=d) return ;
    if (tr[x].n>1) {tr[x].n--;update(x);return ;}
    if (tr[x].son[0]==0&&tr[x].son[1]==0) {root=0;len=0;}
    else if (tr[x].son[0]==0&&tr[x].son[1]!=0) {root=tr[x].son[1];tr[root].f=0;}
    else if (tr[x].son[0]!=0&&tr[x].son[1]==0) {root=tr[x].son[0];tr[root].f=0;}
    else
    {
        int p=tr[x].son[0];
        while (tr[p].son[1]!=0) p=tr[p].son[1];
        splay(p,x);
        int R=p,r=tr[x].son[1];
        tr[R].son[1]=r;
        tr[r].f=R;
        tr[R].f=0;
        root=R;
        update(R);
    }
}
int findqianqu(int d)
{
    int x=findip(d);splay(x,0);
    if (tr[x].d>=d&&tr[x].son[0]!=0)
    {
        x=tr[x].son[0];
        while (tr[x].son[1]!=0) x=tr[x].son[1];
    }
    if (tr[x].d>=d) x=0;
    return x;
}
int findhouji(int d)
{
    int x=findip(d);splay(x,0);
    if (tr[x].d<=d&&tr[x].son[1]!=0)
    {
        x=tr[x].son[1];
        while (tr[x].son[0]!=0) x=tr[x].son[0];
    }
    if (tr[x].d<=d) x=0;
    return x;
}
int findpaiming(int d)
{
    int x=findip(d);splay(x,0);
    return tr[tr[x].son[0]].c+1;
}
int findnum(int k)
{
    int x=root;
    while (1)
    {
        int lc=tr[x].son[0],rc=tr[x].son[1];
        if (k<=tr[lc].c) x=lc;
        else if (k>tr[lc].c+tr[x].n) 
        {
            k-=tr[lc].c+tr[x].n;
            x=rc;
        }
        else break;
    }
    splay(x,0);
    return tr[x].d;
}
void jiagongzi(int x,int d)
{
    tr[x].d+=d;
    if (tr[x].son[0]!=0) jiagongzi(tr[x].son[0],d);
    if (tr[x].son[1]!=0) jiagongzi(tr[x].son[1],d);
}
int main()
{
    int n,meney=0,minm,die=0;
    root=0;len=0;
    scanf("%d%d",&n,&minm);
    for (int i=1;i<=n;i++)
    {
        int a,b;char ch;
        scanf("\n%c ",&ch);
        if (ch=='I') {scanf("%d",&b);if (b<minm) {continue;}else ins(b);}
        else if (ch=='A') 
        { 
            scanf("%d",&b);
            jiagongzi(root,b);
        }
        else if (ch=='S') 
        {
            scanf("%d",&b);
            jiagongzi(root,-b);
            int x=findip(minm);
            if (tr[x].d>=minm)
            {
                splay(x,0);
                if (tr[x].son[0]!=0)
                {   
                    die+=tr[tr[x].son[0]].c;
                    tr[x].son[0]=0;
                    update(x);
                }
            } 
            else 
            {
                x=findhouji(tr[x].d);
                if (x==0)//如果后继为零,也就是说没有人的工资比下界还要大,把整棵树删掉
                {
                    die+=tr[root].c;
                    root=0;len=0;
                    continue;
                }
                splay(x,0);
                if (tr[x].son[0]!=0)
                {
                    die+=tr[tr[x].son[0]].c;
                    tr[x].son[0]=0;
                    update(x);
                }
            }
        }
        else if (ch=='F') {scanf("%d",&b);if (b<=tr[root].c) printf("%d\n",findnum(tr[root].c+1-b));else printf("-1\n");} 
    }
    printf("%d\n",die);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值