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 }

 

posted @ 2019-03-13 22:48  DarkScoCu  阅读(240)  评论(0编辑  收藏  举报