zoukankan      html  css  js  c++  java
  • 刷题总结——郁闷的出纳员(bzoj1503)

    题目:

    题目背景

    NOI2004 DAY1 T1

    题目描述

    OIER 公司是一家大型专业化软件公司,有着数以万计的员工。作为一名出纳员,我的任务之一便是统计每位员工的工资。这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资。如果他心情好,就可能把每位员工的工资加上一个相同的量。反之,如果心情不好,就可能把他们的工资扣除一个相同的量。我真不知道除了调工资他还做什么其它事情。

    工资的频繁调整很让员工反感,尤其是集体扣除工资的时候,一旦某位员工发现自己的工资已经低于了合同规定的工资下界,他就会立刻气愤地离开公司,并且再也不会回来了。每位员工的工资下界都是统一规定的。每当一个人离开公司,我就要从电脑中把他的工资档案删去,同样,每当公司招聘了一位新员工,我就得为他新建一个工资档案。

    老板经常到我这边来询问工资情况,他并不问具体某位员工的工资情况,而是问现在工资第 k 多的员工拿多少工资。每当这时,我就不得不对数万个员工进行一次漫长的排序,然后告诉他答案。

    好了,现在你已经对我的工作了解不少了。正如你猜的那样,我想请你编一个工资统计程序。怎么样,不是很困难吧?

    输入格式

    第一行有两个非负整数 n 和 min 。n 表示下面有多少条命令,min 表示工资下界。
    接下来的 n 行,每行表示一条命令。命令可以是以下四种之一:

        

    “下划线( _ )”表示一个空格,I 命令、A 命令、S 命令中的 k 是一个非负整数,F 命令中的 k 是一个正整数。

    在初始时,可以认为公司里一个员工也没有。

    输出格式

    输出的行数为 F 命令的条数加一。

    对于每条 F 命令,你的程序要输出一行,仅包含一个整数,为当前工资第 k 多的员工所拿的工资数,如果 k 大于目前员工的数目,则输出 -1 。

    输出的最后一行包含一个整数,为离开公司的员工的总数。

    样例数据 1

    输入  [复制]

     
    9 10 
    I 60 
    I 70 
    S 50 
    F 2 
    I 30 
    S 15 
    A 5 
    F 1 
    F 2

    输出

    10 
    20 
    -1 
    2

    备注

    【数据范围】
    I 命令的条数不超过 100000
    A 命令和 S 命令的总条数不超过 100
    F 命令的条数不超过 100000
    每次工资调整的调整量不超过 1000
    新员工的工资不超过 100000

    【评分方法】
    对于每个测试点,如果你输出文件的行数不正确,或者输出文件中含有非法字符,得分为 0 。

    否则你的得分按如下方法计算:

    • 如果对于所有的 F 命令,你都输出了正确的答案,并且最后输出的离开公司的人数也是正确的,你将得到 10 分;
    • 如果你只对所有的 F 命令输出了正确答案,得 6 分;
    • 如果只有离开公司的人数是正确的,得 4 分;否则得 0 分。

    题解:

    重要的事情先说下:

    仔细审题!!!!!

    做的时候以为加入公司就走的员工是要算入总数的·····结果tm不算·····感觉题目也没说清楚啊···

    其余的就是splay的基本操作了···另外这道题有个很巧妙的地方是记录一个sum维护修改公司的总和,并根据sum不是直接修改所有员工的工资数,而是修改加入的人的工资数和每次判断离开公司的人时修改minn(具体看代码)····,这样就能节约复杂度了···

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<ctime>
    #include<cctype>
    #include<cstring>
    #include<string>
    #include<algorithm>
    using namespace std;
    const int N=3e5+5;
    int val[N],father[N],cnt[N],son[N][2],size[N],root,tot;
    int n,a,minn,totl=0,sum=0;
    long long totcut=0;
    char s[5];
    inline int R()
    {
      char c;int f=0;
      for(c=getchar();c<'0'||c>'9';c=getchar());
      for(;c<='9'&&c>='0';c=getchar())
        f=(f<<3)+(f<<1)+c-'0';
      return f;
    }  
    inline void clear(int now)
    {
      size[now]=son[now][0]=son[now][1]=val[now]=cnt[now]=father[now]=0;
    }
    inline void update(int now)
    {
      if(now)
      {
        size[now]=cnt[now];
        if(son[now][0])  size[now]+=size[son[now][0]];
        if(son[now][1])  size[now]+=size[son[now][1]];
      }
    }
    inline int get(int a)
    {
      return son[father[a]][1]==a;
    }
    inline void rotate(int now)
    {
      int fa=father[now],ofa=father[fa],which=get(now);
      son[fa][which]=son[now][which^1],father[son[fa][which]]=fa;
      son[now][which^1]=fa,father[fa]=now,father[now]=ofa;
      if(ofa)  son[ofa][son[ofa][1]==fa]=now;
      update(fa),update(now);
    }
    inline void splay(int now)
    {
      while(father[now])
      {
        if(father[father[now]])  rotate(get(now)==get(father[now])?father[now]:now);
        rotate(now);
      }
      root=now;
    }
    inline void insert(int x)
    { 
      int now=root,last=0;
      while(true)
      {
        if(!now)
        {
          now=++tot;size[now]=cnt[now]=1;father[now]=last;val[now]=x;
          son[last][val[now]>val[last]]=now;update(last);splay(now);
          break;
        }
        if(val[now]==x)
        {
          cnt[now]++;update(now);update(last);splay(now);
          break;
        }
        last=now;now=son[now][x>val[now]];
      }
    }
    inline int findx(int x)
    {
      int now=root;
      while(true)
      {
        if(x<=size[son[now][0]])  now=son[now][0];
        else
        {
          int temp=size[son[now][0]]+cnt[now];
          if(x<=temp)  return val[now];
          x-=temp;now=son[now][1];
        }  
      }
    }
    inline int Delete()
    {
      int temp=size[son[root][0]]+cnt[root];int oldroot=root;
      root=son[oldroot][1];father[root]=0;
      clear(oldroot);
      return temp;
    }
    int main()
    {
      //freopen("a.in","r",stdin);
      n=R(),minn=R();
      while(n--)
      {
        scanf("%s%d",s,&a);
        if(s[0]=='I')
        {
          if(a-sum>(minn-sum-1))  
            insert(a-sum),totl++;
        }
        if(s[0]=='A')
          sum+=a;
        if(s[0]=='S')
          sum-=a;
        if(s[0]=='F')
        {
          if(totl<a)  cout<<"-1"<<endl;
          else
          {
            int ans=findx(totl-a+1);
            cout<<ans+sum<<endl;
          }
        }
        int limit=minn-sum-1;insert(limit);
        int temp=Delete();
        totcut+=(long long)(temp-1);
        totl=totl-temp+1;
      }
      cout<<totcut<<endl;
      return 0;
    }
  • 相关阅读:
    怎么在Vue项目中使用Element组件
    vue-cli 基本使用
    C++ delete指针以后应赋值为NULL
    C++ noexcept异常说明及其使用
    Qt 设置comboBox里面的字体颜色
    Qt 获取可用串口
    Qt 寻找可用串口
    荧光显微镜简介
    荧光滤光片简介
    消色差、半复消色差、复消色差的区别
  • 原文地址:https://www.cnblogs.com/AseanA/p/7492154.html
Copyright © 2011-2022 走看看