本文主要是介绍BZOJ 1208 宠物收养所 Splay树,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Splay的简单应用,找和一个数最接近的数,例如找和x最接近的数,把x旋转到根,要么是左子树的最大值,要么是右子树的最小值。#include <cstdio> #include <cstring> #include <algorithm> #include <cstdlib> using namespace std; typedef long long LL; const int mod = 1000000; const int maxn = 80010; const int INF = 999999999; struct Splay { int pre[maxn], ch[maxn][2], sz[maxn]; int root, top; int val[maxn]; void pushup(int rt) { sz[rt] = sz[ch[rt][0]] + sz[ch[rt][1]] + 1; } void init() { pre[0] = ch[0][0] = ch[0][1] = sz[0] = 0; root = top = 0; } void rotate(int x, int d) { int y = pre[x]; ch[y][d^1] = ch[x][d]; pre[ch[x][d]] = y; if(pre[y]) ch[pre[y]][ch[pre[y]][1] == y] = x; pre[x] = pre[y]; ch[x][d] = y; pre[y] = x; pushup(y); } void splay(int x, int goal) { while(pre[x] != goal) { if(pre[pre[x]] == goal) { rotate(x, ch[pre[x]][0] == x); } else { int y = pre[x], z = pre[y]; int d = (ch[z][0] == y); if(ch[y][d] == x) { rotate(x, d^1); rotate(x, d); } else { rotate(y, d); rotate(x, d); } } } if(goal == 0) root = x; pushup(x); } void NewNode(int &x, int f, int c) { x = ++top; ch[x][0] = ch[x][1] = 0; sz[x] = 1; pre[x] = f; val[x] = c; } void insert(int k) { int x = root; if(x == 0) { NewNode(root, 0, k); return; } while(ch[x][k>val[x]]) x = ch[x][k>val[x]]; NewNode(ch[x][k>val[x]], x, k); splay(ch[x][k>val[x]], 0); pushup(x); } int get_min(int x) { if(!x) return 0; while(ch[x][0]) { x = ch[x][0]; } return x; } int get_max(int x) { if(!x) return 0; while(ch[x][1]) { x = ch[x][1]; } return x; } void remove(int x) { splay(x, 0); if(!ch[root][0] && !ch[root][1]) { root = 0; return; } if(!ch[root][0]) { root = ch[root][1]; pre[root] = 0; } else { int m = get_max(ch[root][0]); splay(m, root); ch[m][1] = ch[root][1]; pre[ch[root][1]] = m; root = m; pre[root] = 0; pushup(root); } } int find(int x) { int rt = root; while(rt) { if(val[rt] == x) return rt; rt = ch[rt][x>val[rt]]; } return rt; } LL cal(int x) { int rt = find(x); LL ans = 0; if(rt != 0) { remove(rt); return 0; } insert(x); int l = ch[root][0], r = ch[root][1]; while(l && ch[l][1]) l = ch[l][1]; while(r && ch[r][0]) r = ch[r][0]; LL d1 = INF, d2 = INF; if(l) d1 = x-val[l]; if(r) d2 = val[r]-x; if(d1 <= d2) { remove(root); remove(l); return d1; } else { remove(root); remove(r); return d2; } } }A, B; int main() { int n; while(scanf("%d", &n) != EOF) { LL ans = 0; A.init(); B.init(); for(int i = 1; i <= n; i++) { int x, y; scanf("%d %d", &x, &y); if(!x) { if(B.sz[B.root] == 0) A.insert(y); else ans += B.cal(y); } else { if(A.sz[A.root] == 0) B.insert(y); else ans += A.cal(y); } ans %= mod; } printf("%lld\n", ans); } return 0; }
这篇关于BZOJ 1208 宠物收养所 Splay树的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!