BZOJ_1503 [NOI2004]郁闷的出纳员 【Splay树】
一 题面
二 分析
模板题。
对于全部员工的涨工资和跌工资,可以设一个变量存储起来,然后在进行删除时,利用伸展树能把结点旋转到根的特性,能够很方便的删除那些不符合值的点。同时,维护的结点数量信息也方便我们进行结果的统计。
三 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 }