BZOJ 1862/1056 ZJOI 2006 GameZ游戏排名系统/ HAOI 2008 排名系统 Treap (双倍经验)

题目大意:维护一种游戏排名系统,为他们的得分排序,若得分一样,则时间早的优先。有的时候要查询一个人是第几名,或者一段名次都是谁。


思路:拿到题一看就知道是暴力Treap乱搞,但是一查不知道看到了谁的文章,说Treap会T,我就战战兢兢的写了Splay,结果T了,拿到数据发现被一个点卡了100s。于是怒写Treap,1.2s怒切。

PS:千万不要相信谣言。。


CODE:

#include <cstdio>
#include <cctype>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 300010
#define MO 299997
#define BASE 133
#define SIZE(a) ((a) == NULL ? 0:(a)->size)
using namespace std;

unsigned long long GetHash(char *s);

struct HashSet{
	int head[MAX],total;
	int next[MAX];
	unsigned long long hash[MAX];
	char src[MAX][12];
	
	int Insert(char *s) {
		unsigned long long _hash = GetHash(s);
		int x = _hash % MO;
		for(int i = head[x]; i; i = next[i])
			if(hash[i] == _hash)
				return i;
		next[++total] = head[x];
		hash[total] = _hash;
		head[x] = total;
		strcpy(src[total],s);
		return total;
	}
}map;

struct Treap{
	int random,val,T,name;
	int size;
	Treap *son[2];
	
	Treap(int _,int __,int ___):val(_),T(__),name(___) {
		size = 1;
		son[0] = son[1] = NULL;
		random = rand();
	}
	int Compare(int _val,int _T) {
		if(_val == val) {
			if(T == _T)	return -1;
			return T < _T;
		}
		return val > _val;
	}
	void Maintain() {
		size = 1;
		if(son[0] != NULL)	size += son[0]->size;
		if(son[1] != NULL)	size += son[1]->size;
	}
}*root = NULL;

int cnt;
int score;
char c,name[12];

int now[MAX],_time[MAX];

unsigned long long GetHash(char *s)
{
	unsigned long long re = 0;
	while(*s != '\0') 
		re = re * BASE + *s++;
	return re;
}

inline void Rotate(Treap *&a,bool dir)
{
	Treap *k = a->son[!dir];
	a->son[!dir] = k->son[dir];
	k->son[dir] = a;
	a->Maintain(),k->Maintain();
	a = k;
}

void Insert(Treap *&a,int score,int t,int name)
{
	if(a == NULL) {
		a = new Treap(score,t,name);
		return ;
	}
	int dir = a->Compare(score,t);
	Insert(a->son[dir],score,t,name);
	if(a->son[dir]->random > a->random)
		Rotate(a,!dir);
	a->Maintain();
}

void Delete(Treap *&a,int score,int t)
{
	int dir = a->Compare(score,t);
	if(dir != -1)
		Delete(a->son[dir],score,t);
	else {
		if(a->son[0] == NULL)	a = a->son[1];
		else if(a->son[1] == NULL)	a = a->son[0];
		else {
			int _ = (a->son[0]->random > a->son[1]->random);
			Rotate(a,_);
			Delete(a->son[_],score,t);
		}
	}
	if(a != NULL)	a->Maintain();
}

int Rank(Treap *a,int k)
{
	if(k <= SIZE(a->son[0]))	return Rank(a->son[0],k);
	k -= SIZE(a->son[0]);
	if(k == 1)	return a->name;
	return Rank(a->son[1],k - 1);
}

int Find(Treap *a,int score,int t)
{
	int dir = a->Compare(score,t);
	if(dir == 0)	return Find(a->son[0],score,t);
	if(dir == -1)	return SIZE(a->son[0]) + 1;
	return SIZE(a->son[0]) + 1 + Find(a->son[1],score,t);
}

int main()
{
	cin >> cnt;
	for(int i = 1; i <= cnt; ++i) {
		while(c = getchar(),c == ' ' || c == '\n' || c == '\r' || c == '\t');
		if(c == '+') {
			scanf("%s%d",name,&score);
			int x = map.Insert(name);
			if(now[x])	Delete(root,now[x],_time[x]);
			now[x] = score,_time[x] = i;
			Insert(root,now[x],_time[x],x);
		}
		else {
			c = getchar();
			ungetc(c,stdin);
			if(isdigit(c)) {
				int st,ed;
				scanf("%d",&st);
				ed = min(st + 9,map.total);
				for(int i = st; i <= ed; ++i) {
					if(i != st)	putchar(' ');
					printf("%s",map.src[Rank(root,i)]);
				}
				puts("");
			}
			else {
				scanf("%s",name);
				int x = map.Insert(name);
				printf("%d\n",Find(root,now[x],_time[x]));
			}
		}
	}	
	return 0;
}


你可能感兴趣的:(2008,treap,2006,平衡树,bzoj,ZJOI,HAOI)