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;
}


1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
题目描述 有一个 $n$ 个点的棋盘,每个点上有一个数字 $a_i$,你需要从 $(1,1)$ 走到 $(n,n)$,每次只能往右或往下走,每个格子只能经过一次,路径上的数字和为 $S$。定义一个点 $(x,y)$ 的权值为 $a_x+a_y$,求所有满足条件的路径中,所有点的权值和的最小值。 输入格式 第一行一个整数 $n$。 接下来 $n$ 行,每行 $n$ 个整数,表示棋盘上每个点的数字。 输出格式 输出一个整数,表示所有满足条件的路径中,所有点的权值和的最小值。 数据范围 $1\leq n\leq 300$ 输入样例 3 1 2 3 4 5 6 7 8 9 输出样例 25 算法1 (树形dp) $O(n^3)$ 我们可以先将所有点的权值求出来,然后将其看作是一个有权值的图,问题就转化为了在这个图中求从 $(1,1)$ 到 $(n,n)$ 的所有路径中,所有点的权值和的最小值。 我们可以使用树形dp来解决这个问题,具体来说,我们可以将这个图看作是一棵树,每个点的父节点是它的前驱或者后继,然后我们从根节点开始,依次向下遍历,对于每个节点,我们可以考虑它的两个儿子,如果它的两个儿子都被遍历过了,那么我们就可以计算出从它的左儿子到它的右儿子的路径中,所有点的权值和的最小值,然后再将这个值加上当前节点的权值,就可以得到从根节点到当前节点的路径中,所有点的权值和的最小值。 时间复杂度 树形dp的时间复杂度是 $O(n^3)$。 C++ 代码 算法2 (动态规划) $O(n^3)$ 我们可以使用动态规划来解决这个问题,具体来说,我们可以定义 $f(i,j,s)$ 表示从 $(1,1)$ 到 $(i,j)$ 的所有路径中,所有点的权值和为 $s$ 的最小值,那么我们就可以得到如下的状态转移方程: $$ f(i,j,s)=\min\{f(i-1,j,s-a_{i,j}),f(i,j-1,s-a_{i,j})\} $$ 其中 $a_{i,j}$ 表示点 $(i,j)$ 的权值。 时间复杂度 动态规划的时间复杂度是 $O(n^3)$。 C++ 代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值