zoukankan      html  css  js  c++  java
  • 题解【bzoj1503 [NOI2004]郁闷的出纳员】

    Description

    给出一个下限 (m) ,要求维护以下操作

    1. 插入一个数(如果小于下限就不加)
    2. 给每个数加上一个数
    3. 给每个数减去一个数,并且删除掉 (< m) 的所有数
    4. 求目前第 (k) 大的数(注意是第 (k) 大!从大到小排序后第 (k) 个)
      最后还要输出所有 3 操作一共删掉了多少个数
      (n leq 10^5)

    Solution

    fhqtreap大法吼!
    由于修改操作是全体操作,可以用一个 (delta) 记录修改总量
    对于 1 操作插入权值 (x - delta)(如果 x <= m 就算了
    对于 2 操作直接把 (delta += x)
    对于 3 操作,先把 (delta -= x) ,然后把小于 (m - delta) 的全部删掉
    具体实现可以 split 出来两个子树,然后直接让 root = 右子树,最后要输出的 ans += 左子树的 siz
    对于 4 操作,split一下就行了

    Code

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 100100; 
    int n, m, delta; 
    struct node {
      int d, rnd, siz; 
      node *ch[2]; 
      inline void upd() { 
        int ret = 1; if(ch[0]) ret += ch[0]->siz; 
        if(ch[1]) ret += ch[1]->siz; siz = ret; 
      }
    }pool[N], *cur = pool, *root; 
    inline int siz(node *p) { return p ? p->siz : 0; }
    inline node *New(int d) { node *p = (cur++); p->d = d, p->siz = 1, p->rnd = rand(); return p; }
    inline node *merge(node *p, node *q) {
      if(!p || !q) return p ? p : q; 
      if(p->rnd  < q->rnd) { p->ch[1] = merge(p->ch[1], q); p->upd(); return p; }
      if(p->rnd >= q->rnd) { q->ch[0] = merge(p, q->ch[0]); q->upd(); return q; }
      return 0; 
    }
    inline void split(node *r, int k, node *&p, node *&q) {
      if(!r) { p = q = 0; return ; }
      if(siz(r->ch[0]) >= k) q = r, split(r->ch[0], k, p, r->ch[0]);
      else p = r, split(r->ch[1], k - siz(p->ch[0]) - 1, r->ch[1], q); r->upd(); 
    }
    inline int rk(node *r, int x) {
      return !r ? 0 : (r->d >= x ? rk(r->ch[0], x) : (siz(r->ch[0]) + 1 + rk(r->ch[1], x))); 
    }
    inline node *del(int x) {
      int k = rk(root, x); node *p, *q; 
      split(root, k, p, q); root = q; return p;  
    }
    int main() { int ans = 0; 
      scanf("%d %d", &n, &m); 
      for(int i = 1; i <= n; i++) {
        char op[5]; int d; 
        scanf("%s %d", op, &d); 
        if(op[0] == 'I') {
          if(d < m) continue ;
          if(!root) { root = New(d - delta); continue ; }
          node *p, *q; split(root, rk(root, d - delta), p, q);
          root = merge(merge(p, New(d - delta)), q);  
        } else if(op[0] == 'A') delta += d; 
        else if(op[0] == 'S') {
          delta -= d; node *p = del(m - delta); 
          ans += siz(p); 
        } else {
          // printf("%d
    ", siz(root)); 
          if(siz(root) < d) { printf("-1
    "); continue ; }
          int sizz = siz(root); 
          node *p, *q, *r; split(root, (sizz - d + 1) - 1, p, q); 
          split(q, 1, q, r); printf("%d
    ", q->d + delta); root = merge(merge(p, q), r);  
        }
      } printf("%d
    ", ans); 
      return 0; 
    }
    
  • 相关阅读:
    样式超出设定宽度显示显示省略号
    客户端存在潜在危险request.from
    MenuStrip如何设置快捷键
    SVN的使用方法
    长串英文字符不换行的解决办法
    thickbox使用
    System.Web.UI.UserControl”,因此此处不允许
    C#中实现拖动无边框Form窗体和窗体的起始位置
    (转)Altera Forum精彩问答汇总
    (转)如何以32 bit的方式存取SDRAM?
  • 原文地址:https://www.cnblogs.com/acfunction/p/10196800.html
Copyright © 2011-2022 走看看