数据结构(Splay平衡树):HAOI2008 排名系统
[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上去!!!
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <string> 5 #include <map> 6 using namespace std; 7 const int maxn=300010; 8 const int INF=2147483647; 9 map<string,int>ID; 10 char c; 11 string name[maxn],str; 12 int rt,cnt,fa[maxn],ch[maxn][2],sz[maxn],key[maxn]; 13 14 void Push_up(int x){ 15 sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1; 16 } 17 18 void Rotate(int x){ 19 int y=fa[x],g=fa[y],c=ch[y][1]==x; 20 ch[y][c]=ch[x][c^1]; 21 if(ch[x][c^1])fa[ch[x][c^1]]=y; 22 ch[x][c^1]=y;fa[y]=x;fa[x]=g; 23 if(g)ch[g][ch[g][1]==y]=x; 24 Push_up(y); 25 } 26 27 void Splay(int x,int g=0){ 28 for(int y;(y=fa[x])!=g;Rotate(x)) 29 if(fa[y]!=g)Rotate((ch[fa[y]][1]==y)==(ch[y][1]==x)?y:x); 30 Push_up(x); 31 if(!g)rt=x; 32 } 33 34 void Get_LR(int x,int &l,int &r){ 35 Splay(x); 36 l=ch[x][0];r=ch[x][1]; 37 while(ch[l][1])l=ch[l][1]; 38 while(ch[r][0])r=ch[r][0]; 39 } 40 41 void Delete(int x){ 42 int l,r; 43 Get_LR(x,l,r); 44 Splay(l);Splay(r,rt); 45 ch[ch[rt][1]][0]=0; 46 Push_up(ch[rt][1]); 47 Push_up(rt); 48 } 49 50 void Insert(int &p,int f,int id,int x){ 51 if(!p){ 52 key[p=id]=x; 53 fa[p]=f; 54 sz[p]=1; 55 Splay(p); 56 return; 57 } 58 sz[p]+=1; 59 Insert(ch[p][key[p]<x],p,id,x); 60 } 61 62 int Get_ID(int k){ 63 int p=rt; 64 while(true){ 65 if(sz[ch[p][0]]+1==k)break; 66 if(sz[ch[p][0]]+1>k)p=ch[p][0]; 67 else k-=sz[ch[p][0]]+1,p=ch[p][1]; 68 } 69 return p; 70 } 71 72 void Print(int p){ 73 if(!p)return; 74 Print(ch[p][1]); 75 cout<<name[p]<<" "; 76 Print(ch[p][0]); 77 } 78 79 void Init(){ 80 Insert(rt,0,1,-INF); 81 Insert(rt,0,2,INF);cnt=2; 82 } 83 84 int main(){ 85 #ifndef ONLINE_JUDGE 86 freopen("rank.in","r",stdin); 87 freopen("rank.out","w",stdout); 88 #endif 89 Init(); 90 int Q,d,tot=0; 91 scanf("%d",&Q); 92 while(Q--){ 93 do c=getchar(); 94 while(c!='+'&&c!='?'); 95 96 if(c=='+'){ 97 cin>>str; 98 scanf("%d",&d); 99 if(ID[str]){ 100 Delete(ID[str]); 101 Insert(rt,0,ID[str],d); 102 } 103 else{ 104 ID[str]=++cnt;tot+=1;name[cnt]=str; 105 Insert(rt,0,ID[str],d); 106 } 107 } 108 else{ 109 cin>>str; 110 if(str[0]<='9'&&str[0]>='0'){ 111 int l,r=0; 112 for(int i=0;str[i];i+=1) 113 r=r*10+(str[i]-'0'); 114 r=tot-r+1;l=max(r-9,1); 115 Splay(Get_ID(l));Splay(Get_ID(r+2),rt); 116 Print(ch[ch[rt][1]][0]); 117 printf("\n"); 118 } 119 else{ 120 Splay(Get_ID(1));Splay(ID[str],rt); 121 printf("%d\n",tot-sz[ch[ch[rt][1]][0]]); 122 } 123 } 124 } 125 return 0; 126 }