1503: [NOI2004]郁闷的出纳员

题目链接

题目大意:给出一个数列(初始为空),给出一个最小值Min,当数列中的数字小于Min时自动删除。四种操作:(1)数列中增加一个元素,设置初始值x;若x小于Min则不插入;(2)所有的元素增加一个值det;(3)所有的元素减小一个值det;此时有可能有一些会被删除(4)询问目前所有元素中第K大的。最后输出删除了多少个。

题解:因为增加减少的操作是对于所有元素的,用一个全局标记tmp记录。
每插入一个元素x,插入x-tmp,这样保证了插入元素的所有真实值都是其节点的值加上tmp
题目中要找第k大,可以维护从大到小的平衡树,也可以转化成第num-k+1小的来做
PS:开始时工资低于mn的不计入离开公司的员工

我的收获:平衡树范围删除,元素个数要用sz[x]来算而非top(因为删除)

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int M=100005;
#define son(x,y) c[c[x][y]][y]

int n,top,x,ans,tmp,z,mn;
int c[M][2],sz[M],k[M];
char opt[10];

inline void pushup(int x){sz[x]=sz[c[x][0]]+sz[c[x][1]]+1;}
inline void node(int &x,int v){x=++top;c[x][0]=c[x][1]=0;sz[x]=1;k[x]=v;}

void rotate(int &x,int k)
{
    int y=c[x][k^1];
    c[x][k^1]=c[y][k];
    c[y][k]=x;pushup(y);
    pushup(x);x=y;
}

void insert(int &x,int v)
{
    if(!x) node(x,v);
    else
    {
        bool m=v>=k[x];
        insert(c[x][m],v);
        if(sz[son(x,m)]>sz[c[x][m^1]])
        rotate(x,m^1);
    }
    pushup(x);
}

int del(int &x,int v)//这个强啊
{  
    int t;
    if(!x) return 0;  
    if(k[x]<v) {t=sz[c[x][0]]+1;x=c[x][1];return t+del(x,v);}
    else {t=del(c[x][0],v);sz[x]-=t;return t;}
}

int select(int &x,int w)
{
    if(!x) return 0; 
    int r=sz[c[x][0]]+1;
    if(w<r) return select(c[x][0],w);
    if(w>r) return select(c[x][1],w-r);
    return k[x];
}

void work()
{
    while(n--){
        scanf("%s%d",opt,&z);
        if(opt[0]=='I') if(z>=mn) insert(x,z-tmp);
        if(opt[0]=='A') tmp+=z;
        if(opt[0]=='S'){tmp-=z;ans+=del(x,mn-tmp);}
        if(opt[0]=='F'){z=select(x,sz[x]-z+1);printf("%d\n",z?z+tmp:-1);}
    }
    printf("%d\n",ans);
}

void init(){
    x=0;top=0;
    cin>>n>>mn;
}

int main()
{
    init();
    work();
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值