排名系统通常要应付三种请求:上传一条新的得分记录、查询某个玩家的当前排名以及返回某个区段内的排名记录。当某个玩家上传自己最新的得分记录时,他原有的得分记录会被删除。为了减轻服务器负担,在返回某个区段内的排名记录时,最多返回10条记录。
Solution
题没什么东西,都是平衡树基本操作,名字的关系用一个 unordered_map
暴力维护即可,就是各种麻烦
(居然写完就AC了?)
#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;
const int N = 300005;
struct SplayTree {
int k[N], sz[N], cnt[N], fa[N], ch[N][2], root;
void pushup(int p) {
sz[p] = sz[ch[p][0]] + sz[ch[p][1]] + cnt[p];
}
void rotate(int p) {
int q = fa[p], y = fa[q], x = ch[q][1] == p;
ch[q][x] = ch[p][x ^ 1]; fa[ch[q][x]] = q;
ch[p][x ^ 1] = q; fa[q] = p; fa[p] = y;
if (y) ch[y][ch[y][1] == q] = p;
pushup(q); pushup(p);
}
void splay(int x) {
for (int y; y = fa[x]; rotate(x))
if (fa[y]) rotate((ch[fa[y]][0] == y) == (ch[y][0] == x) ? y : x);
root = x;
}
int search(int v) {
int p = root;
while (p && (k[p] - v)) p = ch[p][k[p] < v];
return p;
}
void insert(int v,int ind) {
if (root == 0) {
root = ind;
k[root] = v;
sz[root] = cnt[root] = 1;
}
else {
int p = root;
while (p && ch[p][k[p] < v]) p = ch[p][k[p] < v];
ch[p][k[p] < v] = ind;
fa[ind] = p;
k[ind] = v; sz[ind] = cnt[ind] = 1;
splay(ind);
}
}
void remove(int p) {
if (p == 0) return;
splay(p);
if (cnt[p] > 1) { cnt[p]--; sz[p]--; return; }
int l = ch[p][0], r = ch[p][1];
fa[l] = fa[r] = 0; ch[p][0] = ch[p][1] = 0;
if (l == 0) { root = r; return; }
if (r == 0) { root = l; return; }
int t = l;
while (t && ch[t][1]) t = ch[t][1];
root = l; splay(t);
ch[t][1] = r; fa[r] = t;
pushup(t);
}
void remove_v(int v) {
remove(search(v));
}
int rank(int p) {
splay(p);
return sz[ch[p][0]] + 1;
}
int rank_v(int v) {
return rank(search(v));
}
int kth(int p, int k) {
if (k <= sz[ch[p][0]]) return kth(ch[p][0], k);
if (k <= sz[ch[p][0]] + cnt[p]) return p;
else return kth(ch[p][1], k - sz[ch[p][0]] - cnt[p]);
}
int kth(int k0) {
return kth(root, k0);
}
int kth_v(int k0) {
return k[kth(k0)];
}
int prefix(int p) {
splay(p);
int t = ch[p][0];
while (t && ch[t][1]) t = ch[t][1];
return t;
}
int suffix(int p) {
splay(p);
int t = ch[p][1];
while (t && ch[t][0]) t = ch[t][0];
return t;
}
} T;
int m,cnt;
string name[N];
unordered_map <string,int> mp;
signed main() {
ios::sync_with_stdio(false);
cin>>m;
while(m--) {
char c;
cin>>c;
string str; int x;
switch(c) {
case '+':
cin>>str>>x;
if(mp.find(str)==mp.end()) {
++cnt;
mp[str]=cnt;
name[cnt]=str;
T.insert(x,cnt);
}
else {
int p=mp[str];
T.remove(p);
T.insert(x,p);
}
break;
case '?':
cin>>str;
if(str[0]>='0' && str[0]<='9') {
stringstream ss(str);
ss>>x;
int p=T.kth(cnt-x+1);
for(int j=1;j<=10;j++) {
cout<<name[p]<<" ";
p=T.prefix(p);
if(p==0) break;
}
cout<<endl;
}
else {
x=mp[str];
cout<<cnt-T.rank(x)+1<<endl;
}
break;
}
}
}