Description
设计一种数据结构,支持给指定点插入元素并覆盖先前的元素、查询某一点的排名、输出从任意排名之后的10名。
Solution
采用Splay实现
关于读入的字符串,我们可以哈希然后将哈希值丢到map里,这样就可以给每一个字符串一个编号,方便在Splay上操作。
关于插入和删除以及查询操作,都是Splay的基本操作,在此不再赘述。
关于输出答案,我们这样思考:根据BST的性质,当前点的右子树的值一定大于当前点,左子树的值一定小于当前点,也就意味着我们对这棵树进行一次中序遍历就可以得到一个有序序列。那么我们输出答案也是如此,先在右子树中递归输出,在输出当前节点,再进入左子树,同时开一个计数器记录当前输出了多少答案即可。
为了维护Splay的随机性,我们每执行200次操作就随机一个节点并将它延伸到树根。
Code
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef unsigned long long ull; 4 const int INF = 2147483647; 5 const ull mod = 212370440130137957ll; 6 inline int read() { 7 int ret = 0, op = 1; 8 char c = getchar(); 9 while (!isdigit(c)) { 10 if (c == '-') op = -1; 11 c = getchar(); 12 } 13 while (isdigit(c)) { 14 ret = ret * 10 + c - '0'; 15 c = getchar(); 16 } 17 return ret * op; 18 } 19 inline ull rethash(char *aa) { 20 ull ret = 0; 21 int l = strlen(aa + 1); 22 for (register int i = 1; i <= l; ++i) 23 ret = (ret * 131 + aa[i]) % mod; 24 return ret; 25 } 26 inline int retnum(char *aa) { 27 int ret = 0; 28 int l = strlen(aa + 1); 29 for (register int i = 1; i <= l; ++i) 30 ret = ret * 10 + aa[i] - '0'; 31 return ret; 32 } 33 map <ull, int> hash; 34 int n, root, tot, len[250010]; 35 struct Splay { 36 int fa, sum, ch[2], val; 37 } a[250010]; 38 char in[20], name[250010][20]; 39 void update(int now) { 40 a[now].sum = a[a[now].ch[0]].sum + a[a[now].ch[1]].sum + 1; 41 } 42 void connect(int x, int fa, int op) { 43 a[x].fa = fa; 44 a[fa].ch[op] = x; 45 } 46 void rotate(int x) { 47 int y = a[x].fa; 48 int z = a[y].fa; 49 int xson = a[y].ch[1] == x; 50 int yson = a[z].ch[1] == y; 51 int B = a[x].ch[xson ^ 1]; 52 connect(B, y, xson); connect(y, x, xson ^ 1); connect(x, z, yson); 53 update(y); update(x); 54 } 55 void splay(int from, int to) { 56 while (a[from].fa != to) { 57 int y = a[from].fa; 58 int z = a[y].fa; 59 if (z != to) (a[y].ch[0] == from) ^ (a[z].ch[0] == y) ? rotate(from) : rotate(y); 60 rotate(from); 61 } 62 if (to == 0) root = from; 63 } 64 void insert(int val, int x) { 65 int now = root, fa = 0; 66 while (1) { 67 if (!now) { 68 a[x].val = val; 69 a[x].fa = fa; 70 a[x].sum = 1; 71 a[fa].ch[val > a[fa].val] = x; 72 splay(x, 0); 73 return ; 74 } 75 fa = now; 76 now = a[now].ch[val > a[now].val]; 77 } 78 } 79 int query(int x) { 80 int now = root; 81 while (1) { 82 if (x <= a[a[now].ch[0]].sum) now = a[now].ch[0]; 83 else { 84 x -= a[a[now].ch[0]].sum + 1; 85 if (!x) return now; 86 now = a[now].ch[1]; 87 } 88 } 89 } 90 void del(int x) { 91 splay(x, 0); 92 int size = a[a[root].ch[0]].sum; 93 int l = query(size); 94 int r = query(size + 2); 95 splay(l, 0); splay(r, l); 96 a[r].ch[0] = 0; 97 update(r); update(l); 98 a[x].fa = a[x].val = a[x].sum = 0; 99 } 100 void print(int now, int &sum) { 101 if (sum >= 10) return ; 102 if (a[now].ch[1]) print(a[now].ch[1], sum); 103 if (sum >= 10) return ; 104 if (now > 2) { 105 sum++; 106 for (register int i = 1; i < len[now]; ++i) 107 putchar(name[now][i]); 108 putchar(' '); 109 } 110 if (a[now].ch[0]) print(a[now].ch[0], sum); 111 } 112 int main() { 113 srand(20040312); 114 n = read(); 115 insert(-INF, ++tot); insert(INF, ++tot); 116 for (register int i = 1; i <= n; ++i) { 117 scanf("%s", in); 118 if (in[0] == '+') { 119 ull ret = rethash(in); int x = read(); 120 if (hash[ret]) { 121 del(hash[ret]); 122 insert(x, hash[ret]); 123 } 124 else { 125 insert(x, hash[ret] = ++tot); 126 for (register int i = 1; i < strlen(in); ++i) name[tot][i] = in[i]; 127 len[tot] = strlen(in); 128 } 129 } 130 else if (isdigit(in[1])) { 131 int x = retnum(in); 132 int l = query(tot - x + 1); 133 splay(l, 0); 134 int sum = 0; 135 print(a[l].ch[0], sum); 136 puts(""); 137 } 138 else { 139 ull ret = rethash(in); 140 splay(hash[ret], 0); 141 printf("%d ", a[a[root].ch[1]].sum); 142 } 143 if (i % 200 == 0) splay(rand() % tot + 1, 0); 144 } 145 return 0; 146 }