2 条题解
-
0
#include<bits/stdc++.h> using namespace std; const int N = 25e4 + 10; #define lc(p) tr[p].ls #define rc(p) tr[p].rs typedef pair<int, int> PII; struct node { int ls, rs; PII val; int siz; int rnd; } tr[N]; int trlen, root; void pushup(int p) { tr[p].siz = tr[lc(p)].siz + tr[rc(p)].siz + 1; } void split_val(int p, PII v, int &x, int &y) { if (p == 0) { x = y = 0; return ; } if (tr[p].val <= v) { x = p; split_val(rc(p), v, rc(x), y); } else { y = p; split_val(lc(p), v, x, lc(y)); } pushup(p); } // split_rnk 分割后 // x:中序遍历的前 k 个节点(即序列的前 k 项) // y:中序遍历的第 k + 1 个及之后的所有节点(即序列的剩余部分) void split_rnk(int p, int k, int &x, int &y) { if (p == 0) { x = y = 0; return ; } if (tr[lc(p)].siz + 1 <= k) { // 分割线在 p 的右子节点 x = p; split_rnk(rc(p), k - tr[lc(p)].siz - 1, rc(x), y); } else { // 分割线在 p 的左子节点 y = p; split_rnk(lc(p), k, x, lc(y)); } pushup(p); } int merge(int x, int y) { if (x == 0 || y == 0) { return x + y; } if (tr[x].rnd < tr[y].rnd) { rc(x) = merge(rc(x), y); pushup(x); return x; } else { lc(y) = merge(x, lc(y)); pushup(y); return y; } } map<string, PII> mp; map<PII, string> r_mp; int new_tr(PII v) { trlen ++; tr[trlen] = {0, 0, v, 1, rand()}; return trlen; } void ins(PII v) { int x, y; split_val(root, v, x, y); root = merge(merge(x, new_tr(v)), y); } void del(PII v) { int x, y, z; PII _v = {v.first, v.second - 1}; // 刚好在 v 前一个 split_val(root, _v, x, y); split_val(y, v, y, z); root = merge(x, z); } int get_rnk(PII v) { int x, y; split_val(root, v, x, y); // v 是唯一的,直接搜寻到并输出 x 的字数大小 int res = tr[x].siz; root = merge(x, y); return res; } void print_10name(int p) { if (p == 0) { return ; } print_10name(lc(p)); cout << r_mp[tr[p].val] << " "; print_10name(rc(p)); } void get_10name(int k) { int x, y, z; int total = tr[root].siz; int r = min(k + 9, total); int len = r - k + 1; split_rnk(root, k - 1, x, y); // x: [1, k - 1], y: [k, end] split_rnk(y, len, y, z); // y: [k, r] (共 len 个) print_10name(y); cout << "\n"; root = merge(merge(x, y), z); } int main () { ios::sync_with_stdio(false); cin.tie(0); int n; cin >> n; trlen = root = 0; for (int i = 1; i <= n; i ++) { string s; cin >> s; if (s[0] == '+') { string name = s.substr(1); // 从 s 的第一位开始读 int v; cin >> v; PII x = {-v, i}; // 系统里面是从小到大排,我们要求从大到小排 if (mp.count(name)) { // 之前有值就先删了 del(mp[name]); } mp[name] = x; r_mp[x] = name; ins(x); } if (s[0] == '?' && !isdigit(s[1])) { // 第一位不是数字 string name = s.substr(1); cout << get_rnk(mp[name]) << "\n"; } if (s[0] == '?' && isdigit(s[1])) { int k = 0; for (int i = 1; s[i]; i ++) { k = k * 10 + (s[i] - '0'); // 转成数字 } get_10name(k); } } return 0; } -
0
- 1
信息
- ID
- 2709
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 7
- 标签
- 递交数
- 40
- 已通过
- 11
- 上传者