2 条题解

  • 0
    @ 2026-5-9 15:31:36
    #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;
    }
    
    • 1

    信息

    ID
    2709
    时间
    1000ms
    内存
    125MiB
    难度
    7
    标签
    递交数
    40
    已通过
    11
    上传者