[ZJOI2006]GameZ游戏排名系统
Description
GameZ为他们最新推出的游戏开通了一个网站。世界各地的玩家都可以将自己的游戏得分上传到网站上。这样就可以看到自己在世界上的排名。得分越高,排名就越靠前。当两个玩家的名次相同时,先上传记录者优先。由于新游戏的火爆,网站服务器已经难堪重负。为此GameZ雇用了你来帮他们重新开发一套新的核心。排名系统通常要应付三种请求:上传一条新的得分记录、查询某个玩家的当前排名以及返回某个区段内的排名记录。当某个玩家上传自己最新的得分记录时,他原有的得分记录会被删除。为了减轻服务器负担,在返回某个区段内的排名记录时最多返回10条记录。
Input
第一行是一个整数n(n>=10)表示请求总数目。接下来n行每行包含了一个请求。请求的具体格式如下:
+Name Score 上传最新得分记录。Name表示玩家名字,由大写英文字母组成,不超过10个字符。
Score为最多8位的正整数。
?Name 查询玩家排名。该玩家的得分记录必定已经在前面上传。
?Index 返回自第Index名开始的最多10名玩家名字。Index必定合法,即不小于1,也不大于当前有记录的玩家总数。
输入文件总大小不超过2M。
NOTE:用C++的fstream读大规模数据的效率较低
Output
对于每条查询请求,输出相应结果。对于?Name格式的请求,应输出一个整数表示该玩家当前的排名。
对于?Index格式的请求,应在一行中依次输出从第Index名开始的最多10名玩家姓名,用一个空格分隔。
Sample Input
20
+ADAM 1000000
+BOB 1000000
+TOM 2000000
+CATHY 10000000
?TOM
?1
+DAM 100000
+BOB 1200000
+ADAM 900000
+FRANK 12340000
+LEO 9000000
+KAINE 9000000
+GRACE 8000000
+WALT 9000000
+SANDY 8000000
+MICK 9000000
+JACK 7320000
?2
?5
?KAINE
Sample Output
2
CATHY TOM ADAM BOB
CATHY LEO KAINE WALT MICK GRACE SANDY JACK TOM BOB
WALT MICK GRACE SANDY JACK TOM BOB ADAM DAM
4
这题也不是特别难写,主要是字符串处理很烦,其他用splay的基本操作便可以
#include<map>
#include<cmath>
#include<cstdio>
#include<sstream>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7f7f7f7f
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline int read(){
int x=0,f=1;char ch=getchar();
for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1;
for (;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
return x*f;
}
inline void print(int x){
if (x>=10) print(x/10);
putchar(x%10+'0');
}
const int N=3e5;
map<string,int>si;
map<int,string>is;
struct Splay{
#define T(x) (tree[f[x]][1]==x)
#define ls(x) tree[x][0]
#define rs(x) tree[x][1]
int tree[N+10][2],f[N+10],size[N+10],val[N+10];
int root,len,cnt,tot;
void write(int x){
if (!x) return;
write(rs(x));
if (abs(x)!=inf){
printf("%s",is[x].c_str());
++cnt!=tot?putchar(' '):putchar('\n');
}
write(ls(x));
}
void init(){
root=len=2;
val[1]=-inf,val[2]=inf;
f[tree[root][0]=1]=2;
size[1]=1,size[2]=2;
}
void updata(int x){size[x]=size[ls(x)]+size[rs(x)]+1;}
void move(int x){
int fa=f[x],son=tree[x][T(x)^1];
tree[x][T(x)^1]=fa;
tree[fa][T(x)]=son;
if (son) f[son]=fa;
f[x]=f[fa];
if (f[x]) tree[f[x]][T(fa)]=x;
f[fa]=x;
updata(fa),updata(x);
}
void splay(int x){
while (f[x]){
if (f[f[x]]) T(x)==T(f[x])?move(f[x]):move(x);
move(x);
}
root=x;
}
int find(int x,int i){
if (size[ls(i)]+1==x) return i;
if (x<=size[ls(i)]) return find(x,ls(i));
return find(x-size[ls(i)]-1,rs(i));
}
int get_pre(){
int x=ls(root);
while (rs(x)) x=rs(x);
return x;
}
int get_suc(){
int x=rs(root);
while (ls(x)) x=ls(x);
return x;
}
void Delete(int x){
splay(x);
if (!(ls(x)&&rs(x))){
f[root=ls(x)+rs(x)]=0;
f[x]=ls(x)=rs(x)=size[x]=0;
return;
}
int i=get_pre();
splay(i);
f[rs(i)=rs(x)]=i;
f[x]=ls(x)=rs(x)=size[x]=0;
}
void insert(string s,int v){
if (si[s]) Delete(si[s]);
is[si[s]=++len]=s;
val[len]=v;
if (!root){size[root=len]=1;return;}
int i=root;
while (1){
size[i]++;
if (v<=val[i]){
if (!tree[i][0]){f[tree[i][0]=len]=i;break;}
i=tree[i][0];
}else{
if (!tree[i][1]){f[tree[i][1]=len]=i;break;}
i=tree[i][1];
}
}
splay(len);
}
void query(int x){
int r=size[root]-x-1,l=max(1,r-9);
tot=r-l+1,cnt=0;
l=find(l,root),splay(l);
r=find(r+2,root),splay(r);
if (f[l]!=root) move(l);
write(tree[l][1]);
}
void get_Rank(string s){
int x=si[s];
splay(x);
printf("%d\n",size[rs(x)]);
}
}T;
int change(string s){
int x=0;
for (int i=0;i<(int)s.length();i++) x=(x<<1)+(x<<3)+s[i]-'0';
return x;
}
int main(){
T.init();
si.clear(),is.clear();
int n=read();
char ch,c[15];
string s;
for (int i=1;i<=n;i++){
for (ch=getchar();ch!='+'&&ch!='?';ch=getchar());
scanf("%s",c);
s=string(c);
if (ch=='+') T.insert(s,read());
if (ch=='?'){
if (s[0]>='0'&&s[0]<='9'){
int x=change(s);
T.query(x);
}else T.get_Rank(s);
}
}
return 0;
}