★★★☆   输入文件:rank.in   输出文件:rank.out   简单对比
                    时间限制:1 s   内存限制:128 MB

[题目描述]

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

题解:

  用SBT维护每个玩家的记录和上传时间,以记录为第一关键字,时间为第二关键字。因为游戏排名记录越高排名越靠前,所以我让 左子树>根>右子树。如果记录一样,时间不一样,时间靠后的往右子树走,时间靠前的往左子树走。

  用map把字符串与玩家编号(1,2,3.....)建立联系,方便建树。

 #include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
typedef long long LL;
const LL maxn=,base=;
map<unsigned LL,LL> m;
char s[],sname[maxn][];
unsigned long long hash;
LL totnum,tottime,Time[maxn],num[maxn];
LL N,tot,root;
LL tim[maxn],key[maxn],name[maxn],siz[maxn],lc[maxn],rc[maxn];
void r_rotate(LL &rt){
LL k=lc[rt];
lc[rt]=rc[k];
rc[k]=rt;
siz[k]=siz[rt];
siz[rt]=siz[lc[rt]]+siz[rc[rt]]+;
rt=k;
}
void l_rotate(LL &rt){
LL k=rc[rt];
rc[rt]=lc[k];
lc[k]=rt;
siz[k]=siz[rt];
siz[rt]=siz[lc[rt]]+siz[rc[rt]]+;
rt=k;
}
void Maintain(LL &rt,bool flag){
if(flag==false){
if(siz[lc[lc[rt]]]>siz[rc[rt]]) r_rotate(rt);
else if(siz[rc[lc[rt]]]>siz[rc[rt]]){
l_rotate(lc[rt]);
r_rotate(rt);
}
else return;
}
else{
if(siz[rc[rc[rt]]]>siz[lc[rt]]) l_rotate(rt);
else if(siz[lc[rc[rt]]]>siz[lc[rt]]){
r_rotate(rc[rt]);
l_rotate(rt);
}
else return;
}
Maintain(lc[rt],); Maintain(rc[rt],);
Maintain(rt,); Maintain(rt,);
}
void insert(LL &rt,LL player,LL v){
if(rt==){
rt=++tot;
name[rt]=player; key[rt]=v; tim[rt]=Time[player]; //每个节点维护玩家姓名,记录,时间
lc[rt]=rc[rt]=;
siz[rt]=;
return ;
}
siz[rt]++;
if(v>key[rt]) insert(lc[rt],player,v);//排名系统要求key值越大排名越靠前,key值相同,tim值靠后的放在右子树
else insert(rc[rt],player,v);
Maintain(rt,false); Maintain(rt,true);
}
void Delete(LL &rt,LL t,LL v){//删除时间为 t,记录为 v的玩家数据
if((v>key[rt]&&lc[rt]==)||(v<key[rt]&&rc[rt]==)) return ;
siz[rt]--;
if(v==key[rt]){
if(t==tim[rt]){
if(lc[rt]==||rc[rt]==) rt=lc[rt]+rc[rt];
else{
LL u=lc[rt];
while(rc[u]!=) u=rc[u];
name[rt]=name[u]; key[rt]=key[u]; tim[rt]=tim[u];
Delete(lc[rt],tim[u],key[u]);
}
}
else if(t<tim[rt]) Delete(lc[rt],t,v);//tim值小的在左子树
else Delete(rc[rt],t,v);
return ;
}
if(v>key[rt]) Delete(lc[rt],t,v);
else Delete(rc[rt],t,v);
}
LL rank(LL &rt,LL t,LL v){
if(rt==) return (LL);
if(v==key[rt]){
if(t==tim[rt]) return siz[lc[rt]]+(LL);
else if(t<tim[rt]) return rank(lc[rt],t,v);
else return siz[lc[rt]]+(LL)+rank(rc[rt],t,v);
}
if(v>key[rt]) return rank(lc[rt],t,v);
else return siz[lc[rt]]+(LL)+rank(rc[rt],t,v);
}
LL select(LL &rt,LL k){
if(k==siz[lc[rt]]+) return name[rt];
if(k< siz[lc[rt]]+) return select(lc[rt],k);
else return select(rc[rt],k-siz[lc[rt]]-);
}
int main(){
scanf("%lld",&N);
for(LL i=,tmp=;i<=N;i++){
scanf("%s",s);
if(s[]>''||s[]<''){//是 +Name 或 ?Name
for(LL i=;i<strlen(s);i++) hash=hash*base+s[i]-'A'+; //哈希
if(s[]=='+'){//添加记录
scanf("%lld",&tmp);
if(m[hash]==){//是新人
m[hash]=++totnum;// 建立map联系 hash值-->玩家编号
for(int i=;i<strlen(s);i++) sname[totnum][i-]=s[i];// 玩家编号-->名字
}
else Delete(root,Time[m[hash]],num[m[hash]]);//已经有过,删除记录,时间 记录两个关键字都要保证 num[m[hash]]=tmp; Time[m[hash]]=++tottime;//时间要改变
insert(root,m[hash],tmp);
}
else{
printf("%d\n",rank(root,Time[m[hash]],num[m[hash]]));//查询排名
}
}
else{// ?Index 返回自第 Index 名开始的最多10名玩家名字
tmp=;
for(int i=;i<strlen(s);i++) tmp=tmp*+s[i]-'';
for(int i=tmp;i<=tmp+&&i<=siz[root];i++){
int j=select(root,i);//找到玩家编号
if(i!=tmp) printf(" ");
printf("%s",sname[j]);
}
printf("\n");
}
hash=;
}
return ;
}

COGS 197 [HAOI2008] 排名系统的更多相关文章

  1. [HAOI2008]排名系统& [Zjoi2006]GameZ游戏排名系统

    1056: [HAOI2008]排名系统 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2487  Solved: 711[Submit][Statu ...

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

    [HAOI2008] 排名系统 [题目描述] 排名系统通常要应付三种请求:上传一条新的得分记录.查询某个玩家的当前排名以及返回某个区段内的排名记录.当某个玩家上传自己最新的得分记录时,他原有的得分记录 ...

  3. bzoj 1056 [HAOI2008]排名系统(1862 [Zjoi2006]GameZ游戏排名系统)

    1056: [HAOI2008]排名系统 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1854  Solved: 502[Submit][Statu ...

  4. 【BZOJ1056】[HAOI2008]排名系统(Splay)

    [BZOJ1056][HAOI2008]排名系统(Splay) 题面 BZOJ 洛谷 题解 \(Splay\)随便维护一下就好了,至于名字什么的,我懒得手写哈希表了,直接哈希之后拿\(map\)压. ...

  5. BZOJ_1862_[Zjoi2006]GameZ游戏排名系统&&BZOJ_1056_[HAOI2008]排名系统_Splay

    BZOJ_1862_[Zjoi2006]GameZ游戏排名系统&&BZOJ_1056_[HAOI2008]排名系统_Splay Description 排名系统通常要应付三种请求:上传 ...

  6. 2021.12.07 P4291 [HAOI2008]排名系统(Treap)

    2021.12.07 P4291 [HAOI2008]排名系统(Treap) https://www.luogu.com.cn/problem/P4291 双倍经验: https://www.luog ...

  7. 【BZOJ】1862: [Zjoi2006]GameZ游戏排名系统 & 1056: [HAOI2008]排名系统(treap+非常小心)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1862 http://www.lydsy.com/JudgeOnline/problem.php?id ...

  8. 1056: [HAOI2008]排名系统 - BZOJ

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

  9. P4291 [HAOI2008]排名系统

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

随机推荐

  1. 170419、Centos7下完美安装并配置mysql5.6

    首先跟各位说声抱歉,原计划说每天一篇博文,最近由于实在太忙,封闭式开发一个项目,没有时间写博文,望大家见谅!!! 由于公司要搭建分布式服务,我把最近我所用到或者学习的技术或者遇到的问题跟大家分享一下! ...

  2. NoSQL 常用资源

    Hadoop:http://www.apache.org/dyn/closer.cgi/hadoop/common/ easyhadoop:https://github.com/xianglei/ea ...

  3. 【Python算法】归纳、递归、归简

    归简法(reduction) 指的是将某一问题转化成另一个问题,将一个未知问题归简成一个已解决的问题. 归纳法(induction) 首先要证明语句在某一基本情况下是成立的,然后证明他可以由一个对象推 ...

  4. swift tableViewController

    tableViewController 控制器 import UIKit     class ViewController: UITableViewController {              ...

  5. ObjectId

    BSON Types — MongoDB Manual https://docs.mongodb.com/manual/reference/bson-types/#objectid ObjectId ...

  6. 剑指Offer——数组中重复的数字

    题目描述: 在一个长度为n的数组里的所有数字都在0到n-1的范围内. 数组中某些数字是重复的,但不知道有几个数字是重复的.也不知道每个数字重复几次.请找出数组中任意一个重复的数字. 例如,如果输入长度 ...

  7. 病毒侵袭---hdu2896(AC自动机)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2896 输入的字符是所有可见的ASCII码(共有127个)所以要注意一下: 把结果存到一个数组中,然后输 ...

  8. Python自省(反射)指南(转)

    原文:http://www.cnblogs.com/huxi/archive/2011/01/02/1924317.html 在笔者看来,自省和反射是一回事,当然其实我并不十分确定一定以及肯定,所以如 ...

  9. ORM之基础操作进阶

    一.外键自关联(一对多) 1.建表 # 评论表 class Comment(models.Model): id = models.AutoField(primary_key=True) content ...

  10. Html5实现iPhone开机界面

    今天我突发其想,想到可以用HTML5来仿照苹果操作系统做一个能在Web平台运行的iOS. 当然,要开发出一个操作系统,等我再归山修练一百年再说吧.今天就先娱乐一下,先搞一个开机界面. 完工后的图片: ...