数据结构(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 }
时间: 2024-08-05 06:26:53

数据结构(Splay平衡树):HAOI2008 排名系统的相关文章

bzoj 1862/1056 [HAOI2008]排名系统

原题链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1862 很恶心的 一道题,我也不晓得自己是第几次写这题了%>_<%. 写了两种方法,平衡树+哈希和平衡树+map.哈希函数是抄别人的.比较了一下还是哈希快一些. 题意很简单,就不说了. 具体思路是,平衡树维护排名,map建立姓名和分数一一对应的关系. 求rank时题意默认是越先提交得分排名越靠前(相同得分的条件下). 具体如下: 平衡树+map 1 #include<algorit

[haoi2008]排名系统

蛤省省选题. 一道彻头彻尾的码农题. 该题的主要知识点有:字符串hash,平衡树.(两颗平衡树?). 4T用splay怎么都调不过.可能是由于splay常数太大.(想写treap,但又实在不想写). 字符串hash不想写啊,用map水的话时限卡着. 这题就当我过了吧... 过不去的程序: #include<iostream> #include<algorithm> #include<cstring> #include<vector> #include<

P4291 [HAOI2008]排名系统

传送门 怎么主要写的都是平衡树,这种查询排名,查询第 $K$ 大的操作直接权值线段树就行了 把读入的数据离散化一波,然后开个 $map$ 维护每个人最后一次插入时在线段树上的位置,直接线段树维护就完事了 查询排名就询问大于它的节点数量,查询第 $K$ 大直接线段树上二分 就是数据格式比较恶心,细节有点多 #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #inc

bzoj1056 [HAOI2008]排名系统【updating】

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1056 [题解] 就是一棵splay..吧? 一种用map,一种用hash表 本地测hash表跑的飞快,甚至比网络上只跑1s的还快,还是T了...qwq 查不出啊(逃 先晾在这吧,坑再说 map版本: # include <map> # include <stdio.h> # include <string.h> # include <iostream>

数据结构(Splay平衡树):HDU 1890 Robotic Sort

Robotic Sort Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3456    Accepted Submission(s): 1493 Problem Description Somewhere deep in the Czech Technical University buildings, there are labora

数据结构(Splay平衡树):COGS 339. [NOI2005] 维护数列

339. [NOI2005] 维护数列 ★★★★☆   输入文件:seq2005.in   输出文件:seq2005.out   简单对比 时间限制:3 s   内存限制:256 MB [问题描述] 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格) 操作编号 输入文件中的格式 说明 1.  插入 INSERT_posi_tot_c1_c2_..._ctot 在当前数列的第 posi 个数字后插入 tot 个数字:c1, c2,

【pb_ds】bzoj1056 [HAOI2008]排名系统/bzoj1862 [Zjoi2006]GameZ游戏排名系统

STL裸题,线下AC,bzoj无限RE ing…… 1 #include<cstdio> 2 #include<cctype> 3 #include<iostream> 4 #include<string> 5 #include<ext/pb_ds/assoc_container.hpp> 6 #include<ext/pb_ds/tree_policy.hpp> 7 using namespace std; 8 using name

HNOI2008 and ZJOI2006 排名系统

1056: [HAOI2008]排名系统 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1311  Solved: 337[Submit][Status] Description 排名系统通常要应付三种请求:上传一条新的得分记录.查询某个玩家的当前排名以及返回某个区段内的排名记录.当某个玩家上传自己最新的得分记录时,他原有的得分记录会被删除.为了减轻服务器负担,在返回某个区段内的排名记录时,最多返回10条记录. Input 第一行是一个整数n(n

BZOJ 1862: [Zjoi2006]GameZ游戏排名系统 Splay

Splay的基本操作,比较繁琐..... 有个一坑点,sorce会超int 1862: [Zjoi2006]GameZ游戏排名系统 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 913  Solved: 343 [Submit][Status][Discuss] Description GameZ为他们最新推出的游戏开通了一个网站.世界各地的玩家都可以将自己的游戏得分上传到网站上.这样就可以看到自己在世界上的排名.得分越高,排名就越靠前.当两个玩家