您的位置:首页 > 理论基础 > 数据结构算法

数据结构(Splay平衡树):HAOI2008 排名系统

2016-06-16 20:20 387 查看

[HAOI2008] 排名系统

[题目描述]

排名系统通常要应付三种请求:上传一条新的得分记录、查询某个玩家的当前排名以及返回某个区段内的排名记录。当某个玩家上传自己最新的得分记录时,他原有的得分记录会被删除。为了减轻服务器负担,在返回某个区段内的排名记录时,最多返回10条记录。

[输入]

第一行是一个整数n(10<=n<=250000)表示请求总数目。接下来n行,每行包含了一个请求。请求的具体格式如下:

+Name Score 上传最新得分记录。Name表示玩家名字,由大写英文字母组成,不超过10个字符。Score为最多8位的正整数。

?Name 查询玩家排名。该玩家的得分记录必定已经在前面上传。如果两个玩家的得分相同,则先得到该得分的玩家排在前面。

?Index 返回自第Index名开始的最多10名玩家名字。Index必定合法,即不小于1,也不大于当前有记录的玩家总数。

[输出]

对于?Name格式的请求,应输出一个整数表示该玩家当前的排名。

对于?Index格式的请求,应在一行中依次输出从第Index名开始的最多10名玩家姓名,用一个空格分隔。

[样例]

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

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

说明

+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的排名

[数据范围]

20%数据满足N<=100

100%数据满足N<=250000

  数据绝对不是随机的……

  所以每次Insert一定要Splay上去!!!

#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <map>
using namespace std;
const int maxn=300010;
const int INF=2147483647;
map<string,int>ID;
char c;
string name[maxn],str;
int rt,cnt,fa[maxn],ch[maxn][2],sz[maxn],key[maxn];

void Push_up(int x){
sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;
}

void Rotate(int x){
int y=fa[x],g=fa[y],c=ch[y][1]==x;
ch[y][c]=ch[x][c^1];
if(ch[x][c^1])fa[ch[x][c^1]]=y;
ch[x][c^1]=y;fa[y]=x;fa[x]=g;
if(g)ch[g][ch[g][1]==y]=x;
Push_up(y);
}

void Splay(int x,int g=0){
for(int y;(y=fa[x])!=g;Rotate(x))
if(fa[y]!=g)Rotate((ch[fa[y]][1]==y)==(ch[y][1]==x)?y:x);
Push_up(x);
if(!g)rt=x;
}

void Get_LR(int x,int &l,int &r){
Splay(x);
l=ch[x][0];r=ch[x][1];
while(ch[l][1])l=ch[l][1];
while(ch[r][0])r=ch[r][0];
}

void Delete(int x){
int l,r;
Get_LR(x,l,r);
Splay(l);Splay(r,rt);
ch[ch[rt][1]][0]=0;
Push_up(ch[rt][1]);
Push_up(rt);
}

void Insert(int &p,int f,int id,int x){
if(!p){
key[p=id]=x;
fa[p]=f;
sz[p]=1;
Splay(p);
return;
}
sz[p]+=1;
Insert(ch[p][key[p]<x],p,id,x);
}

int Get_ID(int k){
int p=rt;
while(true){
if(sz[ch[p][0]]+1==k)break;
if(sz[ch[p][0]]+1>k)p=ch[p][0];
else k-=sz[ch[p][0]]+1,p=ch[p][1];
}
return p;
}

void Print(int p){
if(!p)return;
Print(ch[p][1]);
cout<<name[p]<<" ";
Print(ch[p][0]);
}

void Init(){
Insert(rt,0,1,-INF);
Insert(rt,0,2,INF);cnt=2;
}

int main(){
#ifndef ONLINE_JUDGE
freopen("rank.in","r",stdin);
freopen("rank.out","w",stdout);
#endif
Init();
int Q,d,tot=0;
scanf("%d",&Q);
while(Q--){
do c=getchar();
while(c!='+'&&c!='?');

if(c=='+'){
cin>>str;
scanf("%d",&d);
if(ID[str]){
Delete(ID[str]);
Insert(rt,0,ID[str],d);
}
else{
ID[str]=++cnt;tot+=1;name[cnt]=str;
Insert(rt,0,ID[str],d);
}
}
else{
cin>>str;
if(str[0]<='9'&&str[0]>='0'){
int l,r=0;
for(int i=0;str[i];i+=1)
r=r*10+(str[i]-'0');
r=tot-r+1;l=max(r-9,1);
Splay(Get_ID(l));Splay(Get_ID(r+2),rt);
Print(ch[ch[rt][1]][0]);
printf("\n");
}
else{
Splay(Get_ID(1));Splay(ID[str],rt);
printf("%d\n",tot-sz[ch[ch[rt][1]][0]]);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: