1056: [HAOI2008]排名系统

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 1854  Solved: 502
[Submit][Status][Discuss]

Description

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

Input


一行是一个整数n(n>=10)表示请求总数目。接下来n行,每行包含了一个请求。请求的具体格式如下: +Name Score
上传最新得分记录。Name表示玩家名字,由大写英文字母组成,不超过10个字符。Score为最多8位的正整数。 ?Name
查询玩家排名。该玩家的得分记录必定已经在前面上传。 ?Index
返回自第Index名开始的最多10名玩家名字。Index必定合法,即不小于1,也不大于当前有记录的玩家总数。

Output

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

Sample Input

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

Sample 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

HINT

100%数据满足N<=250000

【题解】

名次树+哈希表+处理相同结点。

总的思路就是利用名次树维护排名系统,利用插入时间clock标识每个节点,利用哈希表实现由name到插入时间t以及键值v的映射,这样就可以根据(v,t)在ranktree中实现查找。

其中?name操作可以如下完成:

int ans_cnt,ans[maxn];
void query(Node* o,int pos,int pre) {
if(o==NULL) return ;
int s=(o->ch[1]==NULL? 0:o->ch[1]->s);
int rank=pre+s+1;
if(rank>=pos && rank<=pos+9) {
query(o->ch[1],pos,pre);
ans[ans_cnt++]=o->c;
query(o->ch[0],pos,pre+s+1);
}
else {
if(rank<pos) query(o->ch[0],pos,pre+s+1);
else query(o->ch[1],pos,pre);
}
}

需要注意的有:

1)插入时将相同结点插入右子树,虽然可能会出现通过rotate旋转上来的情况,但其t的相对顺序不会发生改变,因此在遍历中如果遇到相等需要通过t判断所处子树的位置。

2) 行末无空格。

     3) 不能以通过不旋转相同结点即破坏堆性质的方法处理相同,刚开始实(zuo)验(si)性试了一下,导致Treap直接退化。

4)bzoj上内存超了就是tle,另外如果要过1862我的代码还需要优化一下hash表以减少空间的浪费。

【代码】

 #include<ctime>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
using namespace std; const int maxn = +;
const int MOD = ; struct Node {
Node *ch[];
int v,r,s,c;
Node(int w,int t) :v(w),c(t) { ch[]=ch[]=NULL; s=; r=rand(); }
int cmp(int x) const {
if(v==x) return -;
return x<v? :;
}
int maintain() {
s=;
if(ch[]!=NULL) s+=ch[]->s;
if(ch[]!=NULL) s+=ch[]->s;
}
};
Node *root;
void rotate(Node* &o,int d) {
Node* k=o->ch[d^]; o->ch[d^]=k->ch[d],k->ch[d]=o;
o->maintain(),k->maintain(),o=k;
}
void insert(Node* &o,int x,int t) {
if(o==NULL) o=new Node(x,t);
else {
int d=x<=o->v? :;
insert(o->ch[d],x,t);
if(o->ch[d]->r > o->r) rotate(o,d^);
}
o->maintain();
}
void remove(Node* &o,int x,int t) {
int d=o->cmp(x);
if(d==- && o->c==t) {
Node *u=o;
if(o->ch[]!=NULL && o->ch[]!=NULL) {
int d2=o->ch[]->r > o->ch[]->r? :;
rotate(o,d2); remove(o->ch[d2],x,t);
}
else {
if(o->ch[]!=NULL) o=o->ch[];
else o=o->ch[]; //ch[0]==NULL && ch[1]==NULL
delete u;
}
}
else {
if(d==-) { if(t<o->c) d=; else d=; }
remove(o->ch[d],x,t);
}
if(o!=NULL) o->maintain();
}
int rank(Node* o,int x,int t) {
if(o==NULL) return -;
int s=o->ch[]==NULL? :o->ch[]->s;
int d=o->cmp(x);
if(d==- && t==o->c) return s+;
else {
if(d==-) { if(t<o->c) d=; else d=; }
if(d==) return s++rank(o->ch[],x,t);
else return rank(o->ch[],x,t);
}
} int n,score,iclock;
char tname[maxn][],s[];
int tt[MOD][],tv[MOD][],size[MOD]; char flag[MOD][][]; int ans_cnt,ans[maxn];
void query(Node* o,int pos,int pre) {
if(o==NULL) return ;
int s=(o->ch[]==NULL? :o->ch[]->s);
int rank=pre+s+;
if(rank>=pos && rank<=pos+) {
query(o->ch[],pos,pre);
ans[ans_cnt++]=o->c;
query(o->ch[],pos,pre+s+);
}
else {
if(rank<pos) query(o->ch[],pos,pre+s+);
else query(o->ch[],pos,pre);
}
}
int hash(char* s) {
int h=;
for(int i=;i<strlen(s);i++) h=h*+s[i]-'A'+,h%=MOD;
return h;
}
int find(char *s) {
int h=hash(s),i=;
while(i<size[h]) { if(strcmp(flag[h][i],s)==) return i; i++;
}
size[h]++; return i;
//cout<<"sz: "<<size[h]<<endl;
} int main() {
freopen("rank.in","r",stdin);
freopen("rank.out","w",stdout);
scanf("%d",&n);
while(n--) {
scanf("%s",s);
int h,r;
if(s[]=='+') {
scanf("%d",&score);
h=hash(s+),r=find(s+);
if(tv[h][r]) remove(root,tv[h][r],tt[h][r]);
insert(root,score,++iclock);
strcpy(tname[iclock],s);
strcpy(flag[h][r],s+);
tt[h][r]=iclock,tv[h][r]=score;
}
else {
if(isalpha(s[])) {
h=hash(s+),r=find(s+);
printf("%d\n",rank(root,tv[h][r],tt[h][r]));
}else {
int pos=;
for(int i=;i<strlen(s);i++) pos=pos*+s[i]-'';
ans_cnt=;
query(root,pos,);
for(int i=;i<ans_cnt;i++) {
printf("%s",tname[ans[i]]+);
if(i<ans_cnt-) putchar(' ');
}
putchar('\n');
}
}
}
return ;
}

bzoj 1056 [HAOI2008]排名系统(1862 [Zjoi2006]GameZ游戏排名系统)的更多相关文章

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

    hash 加上 平衡树(名次树). 这道题麻烦的地方就在于输入的是一个名字,所以需要hash. 这个hash用的是向后探查避免冲突,如果用类似前向星的方式避免冲突,比较难写,容易挂掉,但也速度快些. ...

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

    1862: [Zjoi2006]GameZ游戏排名系统 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1318  Solved: 498[Submit][ ...

  3. 1056/1862. [ZJOI2006]GameZ游戏排名系统【平衡树-splay】

    Description GameZ为他们最新推出的游戏开通了一个网站.世界各地的玩家都可以将自己的游戏得分上传到网站上.这样就可以看到自己在世界上的排名.得分越高,排名就越靠前.当两个玩家的名次相同时 ...

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

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

  5. bzoj 1862: [Zjoi2006]GameZ游戏排名系统 & bzoj 1056: [HAOI2008]排名系统

    傻叉了一晚上,把t打成x,然后这题神奇在于输出一段数,不足的不用输出,一开始我的是直接找没有后面就退,然后这样会格式错误囧……然后最后zj的还卡了下空间,于是不用string就过了……string毁一 ...

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

    STL裸题,线下AC,bzoj无限RE ing…… #include<cstdio> #include<cctype> #include<iostream> #in ...

  7. bzoj1056/1862 [Zjoi2006]GameZ游戏排名系统

    题目链接:1,2 treap恶心题,不多说 #include<algorithm> #include<iostream> #include<cstdlib> #in ...

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

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

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

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

随机推荐

  1. 2015移动安全挑战赛(阿里&看雪主办)第一题分析

    今天在网上看到了阿里移动安全比赛的第一次,并且说难度不大,便拿来看了看. 主体就是找出一个密码输进去,然后看正误. 这个题是纯Java层的一个题,也没用进行什么保护.可以直接反编译. 登陆Button ...

  2. C#编写QQ找茬外挂

    QQ找茬外挂,用C#代码编写. 使用方法 这个工具的主要运行流程很简单:游戏截图->比较图片->标记图片不同点.实现代码 截图的处理类ScreenCapture: /// /// 提供全屏 ...

  3. tomcat 8.0 安装

    tomcat 安装算是非常简单的, 因自己使用ubuntu,所以以下环境均为 ubuntu 操作系统下 tomcat 官方简介 tomcat 各版本下载 这里我使用二进制版本(binary distr ...

  4. MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk

    redis 有如标题所示提示, 可从两方面查找原因: 一, 可以看一下,运行redis实例的用户, 是否对redis, 数据保存的目录有写权限(既然是排查错误,不防把redis所在目录权限最大化试一下 ...

  5. Android Xutils 框架

    XUtils是git上比较活跃 功能比较完善的一个框架,是基于afinal开发的,比afinal稳定性提高了不少,下面是介绍: 鉴于大家的热情,我又写了一篇Android 最火框架XUtils之注解机 ...

  6. C#解leetcode 219. Contains Duplicate II

    该题用到了.NET 3.5在System.Collections.Generic命名空间中包含一个新的集合类:HashSet<T>的Add()方法,详细信息请看转载:C# HashSet ...

  7. 11、SQL Server 视图、数据库快照

    SQL Server 视图 什么是视图? 视图是一个虚拟的表,内容源于查询的结果集.只有当视图上建立了索引后,才会具体化. 视图可以筛选和处理数据,而不是直接访问基础表.如:创建一个视图,只展示源表中 ...

  8. <html:form>、 <html:text>、<html:password>、<html:submit> 标签

    用Struts标签来写表单元件, 引用: <%@ taglib uri="/tags/struts-html" prefix="html" %> 例 ...

  9. (转)MySQL数据库命名规范及约定

    一.[操作规范]1. 如无备注,则表中的第一个id字段一定是主键且为自动增长:2. 如无备注,则数值类型的字段请使用UNSIGNED属性:3. 如无备注,排序字段order_id在程序中默认使用降序排 ...

  10. 了解HTML的代码注释

    什么是代码注释?代码注释的作用是帮助程序员标注代码的用途,过一段时间后再看你所编写的代码,就能很快想起这段代码的用途. 代码注释不仅方便程序员自己回忆起以前代码的用途,还可以帮助其他程序员很快的读懂你 ...