• [BZOJ1503] [NOI2004] 郁闷的出纳员 (treap)


    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

    Solution

      因为每一次的加减工资是对全体员工进行的,所以我们可以对整体打一个$lazy$标记,表示工资的变化情况

      $treap$里记录的是每个人的实际工资$x$减去$lazy$后的值

      那么,对于一个新来的人,他的工资的相对值就是初始工资$k$减$lazy$的值

      查询操作由于要查第$k$大,为了方便,可以从大到小维护$treap$,然后就没什么难点了

      有一个极坑的点:如果一个人初始工资低于$min$,这个人不算做离开公司!!!答案里不算这个人!!!

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 struct treap
     4 {
     5     int l, r, siz, pri, key, val;
     6 }a[100005];
     7 int ans, ptot;
     8 
     9 void push_up(int k)
    10 {
    11     a[k].siz = a[a[k].l].siz + a[a[k].r].siz + a[k].val;
    12 }
    13 
    14 void lturn(int &k)
    15 {
    16     int tmp = a[k].r;
    17     a[k].r = a[tmp].l, a[tmp].l = k;
    18     a[tmp].siz = a[k].siz, push_up(k), k = tmp;
    19 }
    20 
    21 void rturn(int &k)
    22 {
    23     int tmp = a[k].l;
    24     a[k].l = a[tmp].r, a[tmp].r = k;
    25     a[tmp].siz = a[k].siz, push_up(k), k = tmp;
    26 }
    27 
    28 void insert(int &k, int x)
    29 {
    30     if(!k)
    31     {
    32         k = ++ptot, a[k].siz = a[k].val = 1;
    33         a[k].key = x, a[k].pri = rand();
    34         return;
    35     }
    36     ++a[k].siz;
    37     if(x == a[k].key) ++a[k].val;
    38     else if(x > a[k].key)
    39     {
    40         insert(a[k].l, x);
    41         if(a[a[k].l].pri > a[k].pri) rturn(k);
    42     }
    43     else
    44     {
    45         insert(a[k].r, x);
    46         if(a[a[k].r].pri > a[k].pri) lturn(k);
    47     }
    48 }
    49 
    50 void del(int &k, int x)
    51 {
    52     if(!k) return;
    53     if(x <= a[k].key) del(a[k].r, x), push_up(k);
    54     else
    55     {
    56         ans += a[a[k].r].siz + a[k].val;
    57         a[k].r = 0, k = a[k].l;
    58         del(k, x), push_up(k);
    59     }
    60 }
    61 
    62 int find_kth(int k, int x)
    63 {
    64     if(!k) return -1;
    65     if(x <= a[a[k].l].siz) return find_kth(a[k].l, x);
    66     if(x <= a[a[k].l].siz + a[k].val) return k;
    67     return find_kth(a[k].r, x - a[a[k].l].siz - a[k].val);
    68 }
    69 
    70 int main()
    71 {
    72     int n, m, k, root = 0, lazy = 0;
    73     char op[5];
    74     scanf("%d%d", &n, &m);
    75     srand(n);
    76     while(n--)
    77     {
    78         scanf("%s%d", op, &k);
    79         if(op[0] == 'I')
    80         {
    81             if(k < m) continue;
    82             insert(root, k - lazy);
    83         }
    84         if(op[0] == 'A') lazy += k;
    85         if(op[0] == 'S')
    86         {
    87             lazy -= k;
    88             del(root, m - lazy);
    89         }
    90         if(op[0] == 'F')
    91         {
    92             k = find_kth(root, k);
    93             printf("%d
    ", ~k ? a[k].key + lazy : -1);
    94         }
    95     }
    96     printf("%d
    ", ans);
    97     return 0;
    98 }
    View Code
  • 相关阅读:
    HTML5 模板推荐
    OpenCV初探
    微信开放框架-UCToo
    ProFTPD 初探
    移动开发者服务平台-友盟
    线程原理理解
    JVM参数及性能调优
    GC——垃圾回收
    JVM内存模型
    php常用 随机数
  • 原文地址:https://www.cnblogs.com/CtrlCV/p/5615890.html
Copyright © 2020-2023  润新知