1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
| const int INF = 0x3f3f3f3f; struct node { int l, r, val, siz, rnd, cnt; } p[maxn]; int cnt;
inline void update(int id) { p[id].siz = p[p[id].l].siz + p[p[id].r].siz + p[id].cnt; }
void rturn(int &k) { int tmp = p[k].l; p[k].l = p[tmp].r; p[tmp].r = k; p[tmp].siz = p[k].siz; update(k); k = tmp; }
void lturn(int &k) { int tmp = p[k].r; p[k].r = p[tmp].l; p[tmp].l = k; p[tmp].siz = p[k].siz; update(k); k = tmp; }
void insert(int &id, int val) { if (!id) { id = ++cnt; p[id].siz = 1; p[id].cnt = 1; p[id].val = val; p[id].rnd = rand(); return; } p[id].siz++; if (p[id].val == val) p[id].cnt++; else if (p[id].val < val) { insert(p[id].r, val); if (p[p[id].r].rnd < p[id].rnd) lturn(id); } else { insert(p[id].l, val); if (p[p[id].l].rnd < p[id].rnd) rturn(id); } }
void del(int &id, int val) { if (!id) return; if (p[id].val == val) { if (p[id].cnt > 1) { p[id].cnt--; p[id].siz--; } else { if (p[id].l == 0 || p[id].r == 0) id = p[id].l + p[id].r; else if (p[p[id].l].rnd < p[p[id].r].rnd) { rturn(id); del(id, val); } else { lturn(id); del(id, val); } } } else if (val > p[id].val) { p[id].siz--; del(p[id].r, val); } else { p[id].siz--; del(p[id].l, val); } }
int find_rank(int id, int val) { if (id == 0) return 0; if (p[id].val == val) return p[p[id].l].siz + 1; else if (p[id].val < val) return p[p[id].l].siz + p[id].cnt + find_rank(p[id].r, val); else return find_rank(p[id].l, val); }
int kth(int id, int k) { if (k <= p[p[id].l].siz) return kth(p[id].l, k); else if (k > p[p[id].l].siz + p[id].cnt) return kth(p[id].r, k - (p[p[id].l].siz + p[id].cnt)); else return p[id].val; }
int pre(int id, int val) { if (!id) return -INF; if (p[id].val >= val) return pre(p[id].l, val); else return max(p[id].val, pre(p[id].r, val)); }
int nxt(int id, int val) { if (!id) return INF; if (p[id].val <= val) return nxt(p[id].r, val); else return min(p[id].val, nxt(p[id].l, val)); }
|