bzoj1862: [Zjoi2006]GameZ游戏排名系统

时间:2021-03-04 00:05:08

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
加入ADAM的得分记录
+BOB 1000000 加入BOB的得分记录
+TOM 2000000 加入TOM的得分记录
+CATHY
10000000 加入CATHY的得分记录
?TOM 输出TOM目前排名
?1 目前有记录的玩家总数为4,因此应输出第1名到第4名。
+DAM
100000 加入DAM的得分记录
+BOB 1200000 更新BOB的得分记录
+ADAM 900000
更新ADAM的得分记录(即使比原来的差)
+FRANK 12340000 加入FRANK的得分记录
+LEO 9000000
加入LEO的得分记录
+KAINE 9000000 加入KAINE的得分记录
+GRACE 8000000
加入GRACE的得分记录
+WALT 9000000 加入WALT的得分记录
+SANDY 8000000
加入SANDY的得分记录
+MICK 9000000 加入MICK的得分记录
+JACK 7320000 加入JACK的得分记录
?2
目前有记录的玩家总数为12,因此应输出第2名到第11名。
?5 输出第5名到第13名。
?KAINE
输出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
 
 
 
 
题解:
  好久没有写题了,代码能力都不行了·······注意splay处理区间问题一般要加两个哨兵(烧饼)节点,还有这道题n貌似可以到250000(我也不清楚具体多少,反正200000会挂),更坑爹的是Score可以爆int,坑坑坑
code:
 #include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<cassert>
using namespace std;
typedef long long int64;
char ch; bool ok;
void read(int &x){
for (ok=,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=;
for (x=;isdigit(ch);x=x*+ch-'',ch=getchar());
if (ok) x=-x;
}
void read(int64 &x){
for (ok=,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=;
for (x=;isdigit(ch);x=x*+ch-'',ch=getchar());
if (ok) x=-x;
}
const int maxn=;
const int64 inf=9223372036854775807LL;
int q,idx,list[maxn];
int64 x;
char op,tmp[],name[maxn][];
struct Hash{
static const int base1=;
static const int mod1=;
static const int base2=;
static const int mod2=;
int tot,now[mod1],pre[maxn],key[maxn];
void init(){tot=;memset(now,,sizeof(now));}
int find(){
int u=,k=;
for (int i=;tmp[i];i++) u=(u*base1+tmp[i])%mod1,k=(k*base2+tmp[i])%mod2;
for (int p=now[u];p;p=pre[p]) if (key[p]==k) return p;
pre[++tot]=now[u],now[u]=tot,key[tot]=k;
for (int i=;tmp[i];i++) name[tot][i]=tmp[i];
return tot;
}
}data;
struct Splay{
int tot,root,son[maxn][],fa[maxn],siz[maxn],pos[maxn];
int64 val[maxn];
int which(int x){return son[fa[x]][]==x;}
void updata(int x){siz[x]=siz[son[x][]]++siz[son[x][]];}
void rotate(int x){
int y=fa[x],z=fa[y],d=which(x),dd=which(y);
son[y][d]=son[x][d^],fa[son[x][d^]]=y,fa[x]=z;
if (z) son[z][dd]=x;
son[x][d^]=y,fa[y]=x,updata(y),updata(x);
}
void splay(int x){
while (fa[x]){
if (!fa[fa[x]]) rotate(x);
else if (which(fa[x])==which(x)) rotate(fa[x]),rotate(x);
else rotate(x),rotate(x);
}
root=x;
}
void init(){
memset(siz,,sizeof(siz)),memset(pos,,sizeof(pos));
data.init();
root=q+;
siz[q+]=,fa[q+]=,son[q+][]=,son[q+][]=q+,val[q+]=inf;
siz[q+]=,fa[q+]=q+,son[q+][]=son[q+][]=,val[q+]=-inf;
}
int find_left(int x){
for (;son[x][];x=son[x][]);
return x;
}
void del(int x){
splay(x);
int y=find_left(son[x][]);
fa[son[x][]]=fa[son[x][]]=;
splay(y),son[y][]=son[x][],fa[son[x][]]=y,updata(y);
}
void insert(int x){
int f,t;
for (f=t=root;t;f=t,t=son[t][val[x]<=val[t]]);
assert(f!=);
fa[x]=f,son[f][val[x]<=val[f]]=x,splay(x);
}
void push(int64 v){
int id=data.find();
if (pos[id]==) pos[id]=++tot;
else del(pos[id]);
val[id]=v,siz[id]=,fa[id]=son[id][]=son[id][]=,insert(pos[id]);
}
int find(int x,int rank){
if (siz[son[x][]]>=rank) return find(son[x][],rank);
if (siz[son[x][]]+==rank) return x;
return find(son[x][],rank-siz[son[x][]]-);
}
void answer(int x,int rest){
if (rest==||x==) return;
answer(son[x][],rest);
if (siz[son[x][]]<rest){
list[++idx]=x;
answer(son[x][],rest-siz[son[x][]]-);
}
}
void query_list(int rank){
int id=find(root,rank+);
splay(id);
list[idx=]=id;
answer(son[id][],);
if (!name[list[idx]][]) idx--;
for (int i=;i<idx;i++) printf("%s ",name[list[i]]+);
printf("%s\n",name[list[idx]]+);
}
void query_rank(){
int id=data.find();
splay(id),printf("%d\n",siz[son[id][]]);
}
}T;
int main(){
for (read(q),T.init();q;q--){
for (op=getchar();op!='+'&&op!='?';op=getchar());
if (op=='+') scanf("%s",tmp+),read(x),T.push(x);
else if (op=='?'){
scanf("%s",tmp+);
if (isdigit(tmp[])){
x=;
for (int i=;tmp[i];i++) x=x*+tmp[i]-'';
T.query_list(x);
}
else T.query_rank();
}
}
return ;
}