【BZOJ 1862】 [Zjoi2006]GameZ游戏排名系统

原创 2014年11月29日 20:27:46

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

Time Limit: 5 Sec  Memory Limit: 64 MB
Submit: 695  Solved: 265
[Submit][Status]

Description

GameZ为他们最新推出的游戏开通了一个网站。世界各地的玩家都可以将自己的游戏得分上传到网站上。这样就可以看到自己在世界上的排名。得分越高,排名就越靠前。当两个玩家的名次相同时,先上传记录者优先。由于新游戏的火爆,网站服务器已经难堪重负。为此GameZ雇用了你来帮他们重新开发一套新的核心。排名系统通常要应付三种请求:上传一条新的得分记录、查询某个玩家的当前排名以及返回某个区段内的排名记录。当某个玩家上传自己最新的得分记录时,他原有的得分记录会被删除。为了减轻服务器负担,在返回某个区段内的排名记录时,最多返回10条记录。

Input

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

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

HINT

Source


treap+hash。


注意:

1.题中说如果两个人名次相同,先上传者名次靠前,因此用一个no变量记录这个结点是第几个被上传的即可

2.有可能不同名字的hash值相同,因此用前向星来记录

3.求一个人的排名时(Getrank),如果访问到的结点是0,一定要立刻返回0!!

4.排名是从大到小的

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <cstdlib>
#define mod 1000003 
#include <ctime>
#define maxn 500005
using namespace std;
int tot=0,toth=0,root;
char str[100];
struct treap
{
	int l,r,size,data,fix,no;
	char str[20];
}a[maxn];
struct hash
{
	int no,data,ne;
	char str[20];
}hashh[maxn];
int head[mod+5],m;
void Push_up(int x)
{
	a[x].size=a[a[x].l].size+a[a[x].r].size+1;
}
void zag(int &x)
{
	int t=a[x].l;
	a[x].l=a[t].r;
	a[t].r=x;
	a[t].size=a[x].size;
	Push_up(x);
	x=t;
}
void zig(int &x)
{
	int t=a[x].r;
	a[x].r=a[t].l;
	a[t].l=x;
	a[t].size=a[x].size;
	Push_up(x);
	x=t;
}
bool equal(char a[],char b[])
{
	if (strlen(a)!=strlen(b)) return false;
	for (int i=1;i<strlen(a);i++)
	{
		if (a[i]!=b[i]) return false;
	}
	return true;
}
int Hash(char str[])
{
	int x=0;
	for (int i=1;i<strlen(str);i++)
		x*=31,x=x+(str[i]-'A'+1),x%=mod;
	return x;
}
void New_node(int &x,int data,int no)
{
	x=++tot;
	a[x].data=data;
	a[x].no=no;
	a[x].l=a[x].r=0;
	a[x].fix=rand();
	a[x].size=1;
	memcpy(a[x].str,str,strlen(str));
}
void Insert(int &x,int data,int no)
{
	if (!x)
	{
		New_node(x,data,no);
		return;
	}
	a[x].size++;
	if (data<=a[x].data)
	{
		Insert(a[x].l,data,no);
		if (a[a[x].l].fix<a[x].fix) zag(x);
	}
	else
	{
		Insert(a[x].r,data,no);
		if (a[a[x].r].fix<a[x].fix) zig(x);
	}
}
void Delet(int &x,int data,int no)
{
	if (a[x].data==data)
	{
		if (a[x].no==no)     
		{
			if (a[x].l*a[x].r==0) x=a[x].l+a[x].r;
			else if (a[a[x].l].fix<a[a[x].r].fix)
			{
				zag(x);
				Delet(x,data,no);
			}
			else
			{
				zig(x);
				Delet(x,data,no);
			}
		}
		else if (no>a[x].no) 
		{
			a[x].size--;
                        Delet(a[x].l,data,no);
		}
		else
		{
			a[x].size--;
			Delet(a[x].r,data,no);
		}
	}
	else if (data<a[x].data)
	{
		a[x].size--;
		Delet(a[x].l,data,no);
	}
	else
	{
		a[x].size--;
		Delet(a[x].r,data,no);
	}
}
void In(int data,int no)
{
	int h=Hash(str);
	int x=head[h];
	while (x)
	{
		if (equal(hashh[x].str,str))    //如果原来出现过,要先删除,再插入
		{
			Delet(root,hashh[x].data,hashh[x].no);
			hashh[x].no=no;
			hashh[x].data=data;
			Insert(root,data,no);
			return;
		}
		x=hashh[x].ne;
	}
	toth++;    //和tot要区分。。。	hashh[toth].no=no;hashh[toth].data=data;
	memcpy(hashh[toth].str,str,strlen(str));
	hashh[toth].ne=head[h];head[h]=toth;
	Insert(root,data,no);
}
int Getrank(int x,int data,int no)
{
	if (!x) return 0;     //注意!!!
	if (a[x].data==data)
	{
		if (a[x].no==no) return a[a[x].r].size+1;
		if (a[x].no>no) return Getrank(a[x].r,data,no);
		else return Getrank(a[x].l,data,no)+a[a[x].r].size+1;
	}
	if (a[x].data>data) return Getrank(a[x].l,data,no)+a[a[x].r].size+1;
	return Getrank(a[x].r,data,no);
}
void Query()
{
	int h=Hash(str);
	int x=head[h];
	while (x)     //找到被查询的名字的相关信息(data,no)
	{
		if (equal(hashh[x].str,str)) break;
		x=hashh[x].ne;
	}
	printf("%d\n",Getrank(root,hashh[x].data,hashh[x].no));
}
int Findkth(int x,int k)
{
	int s=a[a[x].r].size;
	if (s+1==k) return x;
	if (k<=s) return Findkth(a[x].r,k);
	return Findkth(a[x].l,k-s-1);
}
void Printname()
{
	int x=0;
	for (int i=1;i<strlen(str);i++)
		x*=10,x=x+str[i]-'0';
        for (int i=x;i<=toth&&i<=x+9;i++)
	{
		printf("%s",a[Findkth(root,i)].str+1);
		if (i<toth&&i<x+9) printf(" ");
		else printf("\n");
	}
}
int main()
{
        scanf("%d",&m);
	for (int i=1;i<=m;i++)
	{
		int k;
		scanf("%s",str);
		if (str[0]=='+')
		{
			scanf("%d",&k);
			In(k,i);
		}
		else if (str[1]>='A'&&str[1]<='Z')
		{
			Query();
		}
		else Printname();
	}
	return 0;
}		



一开始加了一句 srand((unsigned)time(NULL))就一直RE,删掉就AC了,不知道为什么。。


相关文章推荐

[BZOJ1862][ZJOI2006]GameZ游戏排名系统(平衡树splay)

美只可以选择两条出路:成为罪恶的粮食,或者,成为罪恶本身。

BZOJ 1862 GameZ游戏排名系统【ZJOI2006】

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1862 因为相同的值不能放在一起,所以我们加一个时间戳来标记相同的数的顺序。题目上说Scor...

BZOJ 1056: [HAOI2008]排名系统 & BZOJ 1862: [Zjoi2006]GameZ游戏排名系统

题目地址:http://www.lydsy.com/JudgeOnline/problem.php?id=1056 & http://www.lydsy.com/JudgeOnline/problem...

1056: [HAOI2008]排名系统&1862: [Zjoi2006]GameZ游戏排名系统&codevs 1985

要求打一个数据结构,支持单点修改,单点排名查询,区间排名查询。 Splay模板题。 可以多加两个节点在两边,开个数组记录玩家在Splay上的位置。 然而bzoj卡cin,又懒,不想打哈希,于是愉...

【BZOJ1056/BZOJ1862】【ZJOI2006】【HAOI2008】游戏排名系统 splay

题意:自己看。 题解:splay。 注意:…………………………我特么在?+数字时只读了一位,导致什么?11啊,?10啊全读成了1。 今天狠下心来写拍子,才,发,现,我就是个大沙茶! ...
  • Vmurder
  • Vmurder
  • 2014年11月16日 09:06
  • 1242

[HAOI2008] 排名系统 & [ZJOI2006] GameZ游戏排名系统 [SPLAY]【数据结构】

题目链接:http://codevs.cn/problem/1985/ ———————————————————————————————————————— 题目描述 Description [HA...

【BZOJ】【P1862】【P1056】【排名系统】【GameZ游戏排名系统】

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

bzoj 1003: [ZJOI2006]物流运输

1003: [ZJOI2006]物流运输 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 7819  Solved: 3273 [Submit][St...

BZOJ 1861 [Zjoi2006] Book 书架

splay

【BZOJ1003】【ZJOI2006】物流运输trans 最短路预处理+动态规划

题解: 首先我们跑出fi,jf_{i,j}表示i到j这些天都是相同路线的最小代价。 然后暴力维护gig_i表示前i天最小代价。 fi,jf_{i,j}可以枚举i,ji,j,暴力处理哪些点不能用,...
  • Vmurder
  • Vmurder
  • 2015年03月23日 20:46
  • 1338
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【BZOJ 1862】 [Zjoi2006]GameZ游戏排名系统
举报原因:
原因补充:

(最多只允许输入30个字)