SPOJ3273.ORDERSET(Treap 模版)

来源:互联网 发布:互联网公司 薪资 知乎 编辑:程序博客网 时间:2024/04/28 11:40

一个空序列,支持过插入一个数,删除一个数,要查询当前序列第 k 大是哪个数,或者比x 小的数有几个。

Treap 模版题

#include <cstdio>#include <cstring>#include <algorithm>#define inf 1500000000using namespace std;typedef long long LL;const int N = 300005;struct treap {int ch[2], val, sz; unsigned int wt;void Set(int vl) { val = vl, wt = rand() * rand() * rand(), sz = 1; }} t[N];int rt, n, tz, q;void update(int x) { t[x].sz = t[t[x].ch[0]].sz + t[t[x].ch[1]].sz + 1; }void rot(int &x, bool ty) { int y = t[x].ch[ty]; t[x].ch[ty] = t[y].ch[!ty], t[y].ch[!ty] = x;update(x), update(y), x = y; }void add(int &x, int val) {if (!x) { t[x = ++ tz].Set(val); return ; }if (t[x].val == val) return ;bool ty = val > t[x].val;add (t[x].ch[ty], val);(t[t[x].ch[ty]].wt > t[x].wt) ? rot(x, ty) : update(x);}void del(int &x, int val) {if (!x) return ;if (t[x].val == val) {bool ty = t[t[x].ch[1]].wt > t[t[x].ch[0]].wt;if (!t[x].ch[ty]) { x = 0; return ; }rot(x, ty), del(t[x].ch[!ty], val);} else del(t[x].ch[val > t[x].val], val);update(x);}int kth(int k) {int x = rt;if (t[x].sz < k) return inf;for (; k != t[t[x].ch[0]].sz + 1;) (k <= t[t[x].ch[0]].sz) ? x = t[x].ch[0] : (k -= t[t[x].ch[0]].sz + 1, x = t[x].ch[1]);return t[x].val;}int Count(int x) {if (!x) return 0;if (t[x].val < q) return Count(t[x].ch[1]) + t[t[x].ch[0]].sz + 1;else return Count(t[x].ch[0]);}void init() {scanf("%d", &n);}void doit() {for (int i = 1; i <= n; i ++) {int x; char ty;scanf (" %c %d", &ty, &x);if (ty == 'I') add(rt, x);else if (ty == 'D') del(rt, x);else if (ty == 'K') {x = kth(x);(x != inf) ? printf ("%d\n", x) : puts("invalid");}else q = x, printf ("%d\n", Count(rt));}}int main(){init();doit();return 0;}


0 0
原创粉丝点击