• BZOJ 1503: [NOI2004]郁闷的出纳员


    1503: [NOI2004]郁闷的出纳员

    Time Limit: 5 Sec  Memory Limit: 64 MB
    Submit: 10527  Solved: 3686
    [Submit][Status][Discuss]

    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

    Source

    分析:

    裸的Splay,对于+k-k的操作想法和NOIP2016D2T2思路相同,插入一个数的时候先减去flo再插入,这样拎出来的时候直接加上flo就好了...

    需要注意的是查询第k大的时候要判一下Splay中还是否存在数字...

    代码:

      1 #include<algorithm>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<cstdio>
      5 //by NeighThorn
      6 using namespace std;
      7 
      8 const int maxn=100000+5;
      9 
     10 int n,Min,flo,ans;
     11 int root,tot,w[maxn],ls[maxn],rs[maxn],fa[maxn],cnt[maxn],siz[maxn];
     12 
     13 char opt[3];
     14 
     15 inline void zig(int x){
     16     int y=fa[x],tmp=siz[y];
     17     if(rs[x])
     18         ls[y]=rs[x],fa[rs[x]]=y,siz[y]=siz[y]-siz[x]+siz[rs[x]],siz[x]=tmp;
     19     else
     20         ls[y]=0,siz[y]=siz[y]-siz[x],siz[x]=tmp;
     21     fa[x]=fa[y];
     22     if(fa[x]){
     23         if(ls[fa[x]]==y)
     24             ls[fa[x]]=x;
     25         else
     26             rs[fa[x]]=x;
     27     }
     28     fa[y]=x,rs[x]=y;
     29 }
     30 
     31 inline void zag(int x){
     32     int y=fa[x],tmp=siz[y];
     33     if(ls[x])
     34         rs[y]=ls[x],fa[ls[x]]=y,siz[y]=siz[y]-siz[x]+siz[ls[x]],siz[x]=tmp;
     35     else
     36         rs[y]=0,siz[y]=siz[y]-siz[x],siz[x]=tmp;
     37     fa[x]=fa[y];
     38     if(fa[x]){
     39         if(ls[fa[x]]==y)
     40             ls[fa[x]]=x;
     41         else
     42             rs[fa[x]]=x;
     43     }
     44     fa[y]=x,ls[x]=y;
     45 }
     46 
     47 inline void splay(int x,int z){
     48     while(fa[x]!=z){
     49         int y=fa[x];
     50         if(fa[y]==z){
     51             if(ls[y]==x)
     52                 zig(x);
     53             else
     54                 zag(x);
     55         }
     56         else{
     57             if(ls[fa[y]]==y){
     58                 if(ls[y]==x)
     59                     zig(y),zig(x);
     60                 else
     61                     zag(x),zig(x);
     62             }
     63             else{
     64                 if(rs[y]==x)
     65                     zag(y),zag(x);
     66                 else
     67                     zig(x),zag(x);
     68             }
     69         }
     70     }
     71     if(!z)
     72         root=x;
     73 }
     74 
     75 inline void ins(int rt,int x){
     76     if(!rt)
     77         w[++tot]=x,siz[tot]=cnt[tot]=1,root=tot;
     78     else if(w[rt]==x)
     79         cnt[rt]++,siz[rt]++,splay(rt,0);
     80     else if(x<w[rt]){
     81         if(!ls[rt])
     82             w[++tot]=x,siz[tot]=cnt[tot]=1,siz[rt]++,fa[tot]=rt,ls[rt]=tot,splay(tot,0);
     83         else
     84             siz[rt]++,ins(ls[rt],x);
     85     }
     86     else{
     87         if(!rs[rt])
     88             w[++tot]=x,siz[tot]=cnt[tot]=1,siz[rt]++,fa[tot]=rt,rs[rt]=tot,splay(tot,0);
     89         else
     90             siz[rt]++,ins(rs[rt],x);
     91     }
     92 }
     93 
     94 inline void del(int rt,int x){
     95     if(w[rt]==x){
     96         splay(rt,0);
     97         if(cnt[rt]>1)
     98             cnt[rt]--,siz[rt]--;
     99         else{
    100             int l=ls[rt],r=rs[rt];
    101             if(!l)
    102                 ls[rt]=rs[rt]=fa[rt]=cnt[rt]=siz[rt]=0,fa[r]=0,root=r;
    103             else{
    104                 while(rs[l])
    105                     l=rs[l];
    106                 splay(l,rt);ls[rt]=rs[rt]=fa[rt]=cnt[rt]=siz[rt]=0;fa[r]=l,rs[l]=r,siz[l]+=siz[r];root=l,fa[l]=0;
    107             }
    108         }
    109     }
    110     else if(x<w[rt])
    111         del(ls[rt],x);
    112     else
    113         del(rs[rt],x);
    114 }
    115 
    116 inline int query(int rt,int x){
    117     if(!ls[rt]){
    118         if(cnt[rt]>=x){
    119             splay(rt,0);
    120             return w[rt];
    121         }
    122         else
    123             return query(rs[rt],x-cnt[rt]);
    124     }
    125     else{
    126         if(siz[ls[rt]]>=x)
    127             return query(ls[rt],x);
    128         else if(siz[ls[rt]]+cnt[rt]>=x){
    129             splay(rt,0);
    130             return w[rt];
    131         }
    132         else
    133             return query(rs[rt],x-cnt[rt]-siz[ls[rt]]);
    134     }
    135 }
    136 
    137 signed main(void){
    138 //    freopen("1503.in","r",stdin);
    139 //    freopen("1503.out","w",stdout);
    140     memset(ls,0,sizeof(ls));
    141     memset(rs,0,sizeof(rs));
    142     memset(fa,0,sizeof(fa));
    143     memset(cnt,0,sizeof(cnt));
    144     memset(siz,0,sizeof(siz));
    145     scanf("%d%d",&n,&Min);root=tot=ans=flo=0;
    146     for(int i=1,x;i<=n;i++){
    147         scanf("%s%d",opt,&x);
    148         if(opt[0]=='I'){
    149             if(x>=Min)
    150                 ins(root,x-flo);
    151         }
    152         else if(opt[0]=='A')
    153             flo+=x;
    154         else if(opt[0]=='S'){
    155             flo-=x;
    156             int s=query(root,1);
    157             while(s+flo<Min){
    158                 del(root,s),ans++;
    159                 if(siz[root]==0)
    160                     break;
    161                 s=query(root,1);
    162             }
    163         }
    164         else{
    165             if(siz[root]<x)
    166                 puts("-1");
    167             else{
    168                 int s=query(root,1);
    169                 while(s+flo<Min){
    170                     del(root,s),ans++;
    171                     if(siz[root]==0)
    172                         break;
    173                     s=query(root,1);
    174                 }
    175                 if(siz[root]<x)
    176                     puts("-1");
    177                 else
    178                     printf("%d
    ",query(root,siz[root]-x+1)+flo);
    179             }
    180         }
    181     }printf("%d
    ",ans);
    182     return 0;
    183 }
    View Code

    by NeighThorn

  • 相关阅读:
    阻止所有普通账号登录服务器
    grep命令
    redis集群配置和节点管理
    redis的安装和配置
    shell特殊字符
    获取docker容器的ip地址
    mysql5.6.38误删除root用户后的一系列问题及解决办法
    CenrOS7.5安装msyql5.7.24
    使用163邮箱的smtp ssl端口发送邮件
    linux统计大文件行数的命令效率大对比
  • 原文地址:https://www.cnblogs.com/neighthorn/p/6163196.html
Copyright © 2020-2023  润新知