fjutacm 2492 宠物收养所 : Splay 模板 O(nlogn)
1 /** 2 problem: http://www.fjutacm.com/Problem.jsp?pid=2492 3 Splay blog: https://tiger0132.blog.luogu.org/slay-notes 4 函数介绍: 5 内部函数: 6 root为指针, x为数值 7 bool check(int root):返回当前结点为父节点的左结点还是右结点(0为左结点,1为右结点) 8 void pushUp(int root):旋转后维护结点信息 9 void rotate(int root):关键函数,旋转结点 10 void splay(int root, int target = 0):Splay核心,将root结点旋转至target子结点,target为0则旋转到树根 11 void find(int x): 将数值为x的结点旋转至树根 12 int pre(int x):寻找数值为x的结点的前驱结点,返回指针 13 int succ(int x):寻找数值为x的结点的后继节点,返回指针 14 外部函数: 15 void clear():清空平衡树 16 void insert(T x):插入数值为x的数 17 int rank(T x):返回数值为x的数为第几小 18 T preAns(T x):返回刚好比数值x小的数是多少 19 T succAns(T x):返回刚好比数值x大的数是多少 20 T kth(int k):返回第k小的数是多少 21 void remove(T x):删除数值为x的结点,如果有多个则数量-1 22 T top(T x):如果有数值为x的结点返回x,否则返回其他数 23 int getAllSize():返回平衡树中有多少个数 24 **/ 25 26 #include<stdio.h> 27 #include<algorithm> 28 #include<queue> 29 using namespace std; 30 31 typedef long long ll; 32 const ll MOD = 1000000; 33 34 template<typename T> 35 class Splay{ 36 const static int MAXN = 10003; 37 const static T INF = 0x3f3f3f3f3f3f3f3fLL; 38 private: 39 struct Node{ 40 int ch[2]; 41 int cnt, size, parent; 42 T val; 43 }node[MAXN]; 44 int treeroot, sign, allSize; 45 queue<int> freeMemory; 46 bool check(int root){ /// right return 1 else return 0 47 return node[node[root].parent].ch[1] == root; 48 } 49 void pushUp(int root){ 50 node[root].size = node[node[root].ch[0]].size + node[node[root].ch[1]].size + node[root].cnt; 51 } 52 void rotate(int root){ 53 int father = node[root].parent, grandpa = node[father].parent, direction = check(root), child = node[root].ch[direction^1]; 54 node[father].ch[direction] = child; node[child].parent = father; 55 node[grandpa].ch[check(father)] = root; node[root].parent = grandpa; 56 node[root].ch[direction^1] = father; node[father].parent = root; 57 pushUp(father); pushUp(root); 58 } 59 void splay(int root, int target = 0){ /// if target == 0 then root to treeroot 60 while(node[root].parent != target){ 61 int father = node[root].parent, grandpa = node[father].parent; 62 if(grandpa != target){ 63 if(check(root) == check(father)) rotate(father); 64 else rotate(root); 65 } 66 rotate(root); 67 } 68 if(!target) treeroot = root; 69 } 70 void find(int x){ 71 if(!treeroot) return; 72 int cur = treeroot; 73 while(node[cur].ch[x > node[cur].val] && node[cur].val != x){ 74 cur = node[cur].ch[x > node[cur].val]; 75 } 76 splay(cur); 77 } 78 int pre(int x){ 79 find(x); 80 if(node[treeroot].val < x) return treeroot; 81 if(!node[treeroot].ch[0]) return -1; 82 int cur = node[treeroot].ch[0]; 83 while(node[cur].ch[1]){ 84 cur = node[cur].ch[1]; 85 } 86 return cur; 87 } 88 int succ(int x){ 89 find(x); 90 if(node[treeroot].val > x) return treeroot; 91 if(!node[treeroot].ch[1]) return -1; 92 int cur = node[treeroot].ch[1]; 93 while(node[cur].ch[0]){ 94 cur = node[cur].ch[0]; 95 } 96 return cur; 97 } 98 public: 99 void clear(){ 100 sign = 0; 101 insert(INF); 102 insert(-INF); 103 allSize = 0; 104 } 105 void insert(T x){ 106 allSize ++; 107 int cur = treeroot, preroot = 0; 108 while(cur && node[cur].val != x){ 109 preroot = cur; 110 cur = node[cur].ch[x > node[cur].val]; 111 } 112 if(cur){ 113 node[cur].cnt ++; 114 }else{ 115 if(freeMemory.empty()) 116 cur = ++ sign; 117 else{ 118 cur = freeMemory.front(); 119 freeMemory.pop(); 120 } 121 if(preroot) node[preroot].ch[x > node[preroot].val] = cur; 122 node[cur].val = x; 123 node[cur].cnt = 1; 124 node[cur].ch[0] = node[cur].ch[1] = 0; 125 node[cur].size = 1; 126 node[cur].parent = preroot; 127 } 128 splay(cur); 129 } 130 int rank(T x){ 131 find(x); 132 return node[node[treeroot].ch[0]].size; 133 } 134 T preAns(T x){ 135 return node[pre(x)].val; 136 } 137 T succAns(T x){ 138 return node[succ(x)].val; 139 } 140 T kth(int k){ 141 k ++; 142 int cur = treeroot; 143 while(1){ 144 if(node[cur].ch[0] && k <= node[node[cur].ch[0]].size){ 145 cur = node[cur].ch[0]; 146 }else if(k > node[node[cur].ch[0]].size + node[cur].cnt){ 147 k -= node[node[cur].ch[0]].size + node[cur].cnt; 148 cur = node[cur].ch[1]; 149 }else{ 150 return node[cur].val; 151 } 152 } 153 } 154 void remove(T x){ 155 allSize --; 156 int last = pre(x), next = succ(x); 157 splay(last), splay(next, last); 158 int del = node[next].ch[0]; 159 if(node[del].cnt > 1){ 160 node[del].cnt --; 161 splay(del); 162 }else{ 163 freeMemory.push(node[next].ch[0]); 164 node[next].ch[0] = 0; 165 } 166 } 167 T top(T x){ 168 find(x); 169 return node[treeroot].val; 170 } 171 int getAllSize(){ 172 return allSize; 173 } 174 }; 175 176 Splay<ll> splay; 177 178 int main(){ 179 int n; 180 ll ans = 0; 181 bool type = 1; 182 scanf("%d", &n); 183 splay.clear(); 184 while(n --){ 185 int a; 186 ll b; 187 scanf("%d%lld", &a, &b); 188 if(a){ 189 if(type || splay.getAllSize() == 0){ 190 splay.insert(b); 191 type = 1; 192 } 193 else{ 194 ll pre = splay.preAns(b), mid = splay.top(b), succ = splay.succAns(b); 195 ll choose; 196 if(abs(pre - b) <= abs(mid - b)){ 197 choose = pre; 198 }else{ 199 choose = mid; 200 } 201 if(abs(choose - b) > abs(succ - b)){ 202 choose = succ; 203 } 204 ans = (ans + abs(choose - b)) % MOD; 205 splay.remove(choose); 206 } 207 }else{ 208 if(!type || splay.getAllSize() == 0){ 209 splay.insert(b); 210 type = 0; 211 } 212 else{ 213 ll pre = splay.preAns(b), mid = splay.top(b), succ = splay.succAns(b); 214 ll choose; 215 if(abs(pre - b) <= abs(mid - b)){ 216 choose = pre; 217 }else{ 218 choose = mid; 219 } 220 if(abs(choose - b) > abs(succ - b)){ 221 choose = succ; 222 } 223 ans = (ans + abs(choose - b)) % MOD; 224 splay.remove(choose); 225 } 226 } 227 } 228 printf("%lld\n", ans); 229 return 0; 230 }