数据结构(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; }
相关文章推荐