【HAOI2008】排名系统

【题目描述】

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

【输入格式】

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

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

?Name 查询玩家排名。该玩家的得分记录必定已经在前面上传。

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

【输出格式】

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

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

【样例输入】

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

【样例输出】

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

【时间限制】

1s

【数据范围】

20%数据满足N<=100

100%数据满足N<=250000

【题解】

平衡树+哈希

将名字存在哈希表中,每次新插入一条信息就现在哈希表中找看之前有没有记录,如果有就删除,然后插入。

但是有个问题,如果你要删的值和结点值相同但是姓名不同,你怎么知道要删左子树还是右子树??

于是结点还要记录下每个记录时间,删除时只要时间和值相同就行了。

接下来就是平衡树的基本操作了。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<cstdlib>
  6 #include<ctime>
  7 #include<algorithm>
  8 using namespace std;
  9 const int INF=985003;
 10 int n,root,tot,len,head[INF+10];
 11 struct node1{int v,next,time;char ch[10];}hash[250010];
 12 struct node2{int v,time,fix,size,l,r;  char ch[10];}tr[250010];
 13 void updata(int p) {tr[p].size=tr[tr[p].l].size+tr[tr[p].r].size+1;}
 14 void lturn(int &p) {int c=tr[p].r; tr[p].r=tr[c].l; tr[c].l=p; tr[c].size=tr[p].size; updata(p); p=c;}
 15 void rturn(int &p) {int c=tr[p].l; tr[p].l=tr[c].r; tr[c].r=p; tr[c].size=tr[p].size; updata(p); p=c;}
 16 bool cmp(char a[],char b[]) {for(int i=1;i<max(strlen(a),strlen(b));i++) if(a[i]!=b[i]) return 0;return 1;}
 17 int Hash(char ch[]) {int s=0; for(int i=1;i<strlen(ch);i++) {s*=27; s+=ch[i]-‘A‘+1; s%=INF;} return s;}
 18 void insert(int &p,int v,int time,char ch[])
 19 {
 20     if(!p)
 21     {
 22         p=++len; tr[p].size=1; tr[p].v=v; tr[p].time=time; tr[p].fix=rand();
 23         memcpy(tr[p].ch,ch,strlen(ch)); return;
 24     }
 25     tr[p].size++;
 26     if(v<=tr[p].v)  {insert(tr[p].l,v,time,ch);  if(tr[p].fix>tr[tr[p].l].fix)  rturn(p);}
 27     else {insert(tr[p].r,v,time,ch);  if(tr[p].fix>tr[tr[p].r].fix) lturn(p);}
 28 }
 29 void del(int &p,int v,int time)
 30 {
 31     if(v==tr[p].v)
 32     {
 33         if(time==tr[p].time)
 34         {
 35             if(tr[p].l*tr[p].r==0)  p=tr[p].l+tr[p].r;
 36             else if(tr[tr[p].l].fix<tr[tr[p].r].fix)  {rturn(p);  del(p,v,time);}
 37             else {lturn(p);  del(p,v,time);}
 38         }
 39         else if(time>tr[p].time)  {tr[p].size--; del(tr[p].l,v,time);}
 40         else {tr[p].size--; del(tr[p].r,v,time);}
 41     }
 42     else if(v<tr[p].v)  {tr[p].size--;  del(tr[p].l,v,time);}
 43     else {tr[p].size--;  del(tr[p].r,v,time);}
 44 }
 45 void work(char ch[],int x,int time)
 46 {
 47     int k=Hash(ch);  int i=head[k];
 48     while(i)
 49     {
 50         if(cmp(hash[i].ch,ch))
 51         {
 52             del(root,hash[i].v,hash[i].time);
 53             hash[i].time=time;  hash[i].v=x;
 54             insert(root,x,time,ch);
 55             return;
 56         }
 57         i=hash[i].next;
 58     }
 59     tot++;
 60     hash[tot].time=time;  hash[tot].v=x;
 61     hash[tot].next=head[k];  head[k]=tot;
 62     memcpy(hash[tot].ch,ch,strlen(ch));
 63     insert(root,x,time,ch);
 64 }
 65 int get(char ch[])
 66 {
 67     int k=Hash(ch);int i=head[k];
 68     while(i)
 69     {
 70         if(cmp(hash[i].ch,ch))return i;
 71         i=hash[i].next;
 72     }
 73 }
 74 int rank(int p,int v,int time)
 75 {
 76     if(p==0)  return 0;
 77     if(tr[p].v==v)
 78     {
 79         if(tr[p].time==time)  return tr[tr[p].r].size+1;
 80         else if(time<tr[p].time)  return rank(tr[p].r,v,time);
 81         else return tr[tr[p].r].size+1+rank(tr[p].l,v,time);
 82     }
 83     else if(v>tr[p].v)  return rank(tr[p].r,v,time);
 84     else return tr[tr[p].r].size+1+rank(tr[p].l,v,time);
 85 }
 86 void ask1(char ch[])
 87 {
 88     int t=get(ch);
 89     printf("%d\n",rank(root,hash[t].v,hash[t].time));
 90 }
 91 int index(int k,int x)
 92 {
 93     if(tr[tr[k].r].size+1==x)return k;
 94     else if(x<=tr[tr[k].r].size)return index(tr[k].r,x);
 95     else return index(tr[k].l,x-tr[tr[k].r].size-1);
 96 }
 97 void ask2(char ch[])
 98 {
 99     int s=0;
100     for(int i=1;i<strlen(ch);i++){s*=10;s+=ch[i]-‘0‘;}
101     for(int i=s;i<=tot&&i<=s+9;i++)
102     {
103        printf("%s",tr[index(root,i)].ch+1);
104        if(i<tot&&i<s+9)printf(" ");
105     }
106     printf("\n");
107 }
108 int main()
109 {
110     freopen("cin.in","r",stdin);
111     freopen("cout.out","w",stdout);
112     scanf("%d",&n);  char ch[11];  int x;
113     for(int i=1;i<=n;i++)
114     {
115         scanf("%s",ch);
116         if(ch[0]==‘+‘)  {scanf("%d",&x);  work(ch,x,i);}
117         else if(ch[1]>=‘A‘&&ch[1]<=‘Z‘) ask1(ch);
118         else ask2(ch);
119     }
120     return 0;
121 }

时间: 2024-08-29 03:06:52

【HAOI2008】排名系统的相关文章

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

[HAOI2008] 排名系统 [题目描述] 排名系统通常要应付三种请求:上传一条新的得分记录.查询某个玩家的当前排名以及返回某个区段内的排名记录.当某个玩家上传自己最新的得分记录时,他原有的得分记录会被删除.为了减轻服务器负担,在返回某个区段内的排名记录时,最多返回10条记录. [输入] 第一行是一个整数n(10<=n<=250000)表示请求总数目.接下来n行,每行包含了一个请求.请求的具体格式如下: +Name Score 上传最新得分记录.Name表示玩家名字,由大写英文字母组成,不超

bzoj 1862/1056 [HAOI2008]排名系统

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

P4291 [HAOI2008]排名系统

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

[haoi2008]排名系统

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

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>

【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为他们最新推出的游戏开通了一个网站.世界各地的玩家都可以将自己的游戏得分上传到网站上.这样就可以看到自己在世界上的排名.得分越高,排名就越靠前.当两个玩家

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

1862: [Zjoi2006]GameZ游戏排名系统 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1318  Solved: 498[Submit][Status][Discuss] Description GameZ为他们最新推出的游戏开通了一个网站.世界各地的玩家都可以将自己的游戏得分上传到网站上.这样就可以看到自己在世界上的排名.得分越高,排名就越靠前.当两个玩家的名次相同时,先上传记录者优先.由于新游戏的火爆,网站服务器已经难堪重负.为此