• bzoj1503 郁闷的出纳员(平衡树,思维)


    题目大意:
    现在有n个操作和一个最低限度m

    (I)命令(I k)新建一个工资档案,初始工资为k。
    (A)命令$A k $把每位员工的工资加上k

    (S)命令$S k $把每位员工的工资扣除k

    (F)命令$ F k(查询第k多的工资 (如果当前的员工总数不够k,就输出)-1$)

    其中(n le 100000)

    最后还要输出最终离开了多少个员工

    需要注意的是 ,如果某员工的初始工资低于工资下界,他将立刻离开公司!!!!

    一看这个题,就感觉是个(splay)

    不过emmmm 这个整体加和整体减应该怎么弄呢

    我们考虑维护一个整体的变化值(tmp)

    那么对于splay中的每个元素,它的实际权值就是(x+tmp)

    这么来说

    对于(I)操作,如果它的权值(>)m,则(insert(x-tmp))

    对于(A)操作,直接(tmp+=x)

    对于(S)操作,我们让(tmp-=x),并且判断有没有需要退出的点(就是直接将(-inf)转到(root),然后把(min1-tmp-1)的后继转到root的右儿子,删掉左儿子)这样做的原因是避免哨兵被删掉

    对于(F)操作,那就直接返回第k大,然后(+tmp)就可以

    代码还是有很多细节的,比如要维护当前平衡树中有几个元素,事先加入哨兵之类的,直接看代码吧

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<map>
    #include<queue>
    #include<vector>
    
    using namespace std;
    
    inline int read()
    {
       int x=0,f=1;char ch=getchar();
       while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
       while (isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
       return x*f;
    }
    
    const int maxn = 1e6+1e2;
    
    int ch[maxn][4];
    int val[maxn],sz[maxn],size;
    int fa[maxn];
    int cnt[maxn];
    int n,m,ymh,root,min1;
    int tot;
    int num=0;
    int ans;
    
    int son(int x)
    {
        if (x==ch[fa[x]][0]) return 0;
        else return 1;
    }
    void update(int x)
    {
        sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+cnt[x];
    }
    
    void rotate(int x)
    {
        int y=fa[x],z=fa[y];
        int b=son(x),c=son(y);
        ch[z][c]=x;
        fa[x]=z;
        ch[y][b]=ch[x][!b];
        fa[ch[x][!b]]=y;
        ch[x][!b]=y;
        fa[y]=x;
        update(y);
        update(x);
    }
    
    void splay(int x,int p)
    {
        while (fa[x]!=p)
        {
            int y=fa[x],z=fa[y];
            if (z==p) rotate(x);
            else
            {
                if (son(x)==son(y))
                {
                    rotate(y);
                    rotate(x);
                }
                else
                {
                    rotate(x);
                    rotate(x);
                }
            }
        }
        if (fa[x]==0) root=x;
    }
    
    int find_qq(int x)
    {
        int now = root,num=0;
        while (now)
        {
            if (val[now]<x)
            {
                num=now;
                now=ch[now][1];
            }
            else now=ch[now][0];
        }
        return num;
    }
    
    int find_hj(int x)
    {
        int now = root,num=0;
        while (now)
        {
            if (val[now]>x)
            {
                num=now;
                now=ch[now][0];
            }
            else now=ch[now][1];
        }
        return num;
    }
    
    void insert(int x)
    {
        tot++;
        int qq = find_qq(x);
        int hj = find_hj(x);
        splay(qq,0);
        splay(hj,qq);
        int y = ch[hj][0];
        if (cnt[y])
        {
            cnt[y]++;
            update(y);
        }
        else
        {
            ++size;
            ch[hj][0]=size;
            fa[size]=hj;
            val[size]=x;
            cnt[size]=1;
            sz[size]=1;
            //cout<<"gg11"<<endl;
            update(size);
        }
    }
    
    void delet(int x)
    {
        --tot;
        int qq = find_qq(x);
        int hj = find_hj(x);
        splay(qq,0);
        splay(hj,qq);
        int y = ch[hj][0];
        if (cnt[y]>1)
        {
            cnt[y]--;
            update(y);
        }
        else
        {
            cnt[y]=0;
            fa[y]=0;
            ch[hj][0]=0;
            sz[y]=0;
            val[y]=0;	
        }
    }
    
    int kth(int x)
    {
        int now = root;
        while (1)
        {
            if (x<=sz[ch[now][0]]) now=ch[now][0];
            else{
                if (x<=sz[ch[now][0]]+cnt[now]) return val[now];
                x-=sz[ch[now][0]]+cnt[now];
                now=ch[now][1];	
              }
        }
    }
    
    int add;
    
    int main()
    {
      size=2;
      val[1]=2e9;
      val[2]=-2e9;
      fa[2]=1;
      ch[1][0]=2;
      root=1;
      scanf("%d%d",&n,&min1);
      for (int i=1;i<=n;i++)
      {
      	char s[10];
        int x;
      	scanf("%s",s+1);
      	//cout<<size<<endl;
      	x=read();
      	//cout<<x<<endl;
      	if (s[1]=='A')
      	{
      		ymh+=x;
          }
        if (s[1]=='S')
        {
            ymh-=x;
            int hj = find_hj(min1-ymh-1);
            splay(2,0);
            splay(hj,2);
            int pos = ch[hj][0];
            ans+=sz[pos];
            tot-=sz[pos];
            fa[pos]=0;
            ch[hj][0]=0;
            sz[pos]=0;
            cnt[pos]=0;
            /*if (tot==0) 
            {
           	size=2;
                val[1]=2e9;
                val[2]=-2e9;
                fa[2]=1;
                ch[1][0]=2;
                root=1;
            }*/
            //cout<<ans;
        }
        if (s[1]=='I')
        {
            if (x<min1) continue;
            //cout<<"gg"<<endl;
            insert(x-ymh);
        }
        if (s[1]=='F')
        {
            //cout<<tot<<endl;
            if (x>tot)
              printf("-1
    ");
            else
           	  printf("%d
    ",kth(tot-x+1)+ymh); 
        }
        //cout<<tot<<endl;
      }
      cout<<ans;
      return 0;
    }
    
    
  • 相关阅读:
    js检验文件格式
    java判空工具类
    $(document).ready() 是个什么函数?为什么要用它?
    Maven 手动添加jar
    java深克隆
    cors跨域详解
    常见异常类总结
    Spring事务回滚机制
    Java获取13位毫秒级时间戳
    JSON 字符串转换为 Map
  • 原文地址:https://www.cnblogs.com/yimmortal/p/10160798.html
Copyright © 2020-2023  润新知