BZOJ_1503 [NOI2004]郁闷的出纳员 【Splay树】

一 题面

  [NOI2004]郁闷的出纳员

二 分析

  模板题。

  对于全部员工的涨工资和跌工资,可以设一个变量存储起来,然后在进行删除时,利用伸展树能把结点旋转到根的特性,能够很方便的删除那些不符合值的点。同时,维护的结点数量信息也方便我们进行结果的统计。

三 AC代码

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <iostream>
  5 #include <fstream>
  6 using namespace std;
  7 
  8 const int MAXN = 1e5 + 15;
  9 class Splay
 10 {
 11 public:
 12     struct Node
 13     {
 14         Node *ch[2], *fa;
 15         int size, key;
 16         Node(){
 17             ch[0] = ch[1] = fa = NULL;
 18             key = size = 0;
 19         }
 20         void setc(Node *p, bool d){
 21             ch[d] = p;
 22             p->fa = this;
 23         }
 24         //判断是父节点的哪个孩子结点
 25         bool d(){
 26             //是父节点的有儿子
 27             return fa->ch[1] == this;
 28         }
 29         void push_up(){
 30             size = ch[0]->size + ch[1]->size + 1;
 31         }
 32     }*null, *root;
 33     Splay(){
 34         null = new Node;
 35         null->ch[0] = null->ch[1] = null->fa = null;
 36         root = null;
 37     }
 38     void rotate(Node *rt){
 39         Node* fa = rt->fa;
 40         bool d = rt->d();
 41         fa->fa->setc(rt, fa->d());
 42         fa->setc(rt->ch[!d], d);
 43         rt->setc(fa, !d);
 44         fa->push_up();
 45         if(root == fa)  root = rt;
 46     }
 47     Node* newNode(const int &key){
 48         Node* rt = new Node();
 49         rt->key = key;
 50         rt->size = 1;
 51         rt->ch[0] = rt->ch[1] = rt->fa = null;
 52         return rt;
 53     }
 54     void splay(Node* rt, Node* fa){
 55         while(rt->fa != fa){
 56             if(rt->fa->fa == fa)
 57                 rotate(rt);
 58             else{
 59                 //容易出错的位置
 60                 rt->d() == rt->fa->d() ? rotate(rt->fa) : rotate(rt);
 61                 rotate(rt);
 62             }
 63         }
 64         rt->push_up();
 65     }
 66     void insert(const int &key){
 67         if(root == null){
 68             root = newNode(key);
 69             return;
 70         }
 71         Node* t = root;
 72         while(t->ch[key > t->key] != null)
 73             t = t->ch[key > t->key];
 74         Node* c = newNode(key);
 75         t->setc(c, key > t->key);
 76         t->push_up();
 77         splay(c, null);
 78     }
 79     Node* get_kth(Node* rt, int k){
 80         Node* x = rt;
 81         if(x == null)
 82             return null;
 83         while(x->ch[0]->size + 1 != k){
 84             if(k < x->ch[0]->size + 1)
 85                 x = x->ch[0];
 86             else{
 87                 k -= x->ch[0]->size + 1;
 88                 x = x->ch[1];
 89             }
 90         }
 91         return x;
 92     }
 93 };
 94 
 95 int main()
 96 {
 97     //freopen("input.txt", "r", stdin);
 98     //freopen("out.txt", "w", stdout);
 99     int n, min, k;
100     int data = 0, Cnt = 0;
101     char c;
102     Splay sptree;
103     scanf("%d %d", &n, &min);
104     while(n--){
105         getchar();
106         scanf("%c %d", &c, &k);
107         if(c == 'I'){
108             if(k < min)
109                 continue;
110             sptree.insert(k+data);
111         }
112         else if(c == 'A'){
113             data -= k;
114         }
115         else if(c == 'S'){
116             data += k;
117             sptree.insert(min+data);
118             Cnt += sptree.root->ch[0]->size;
119             sptree.root=sptree.root->ch[1];
120             sptree.root->fa = sptree.null;
121         }
122         else{
123             if(k > sptree.root->size)
124                 printf("-1\n");
125             else{
126                 k = sptree.root->size - k + 1;
127                 printf("%d\n", sptree.get_kth(sptree.root, k)->key-data);
128             }
129         }
130     }
131     printf("%d\n", Cnt);
132     return 0;
133 }
View Code

 

posted @ 2019-05-07 23:23  Dybala21  阅读(114)  评论(0编辑  收藏  举报