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

题目链接http://www.lydsy.com/JudgeOnline/problem.php?id=1862

因为相同的值不能放在一起,所以我们加一个时间戳来标记相同的数的顺序。题目上说Score的范围是8位正整数,但我在06年的数据中发现了0,甚至还有10位正整数!坑了我好久。BZOJ上没有数据范围。。。我的结构体大小是一个个试出来的。。。代码比较渣。。。

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

const int inf = 0x7fffffff - 1;

struct Node {
	int val,id,sz;
	Node *fa,*ch[2];
}*root,*null,Tr[400000+10],*node[400000+10];

struct Trie {
	int ch[26];
	bool value;
}T[400000+10];

int n,cnt,Tcnt,ticnt,ddcnt;

bool is;

int C[400000+10],fa[400000+10],ti[400000+10];

char s[1000+10];

Node* Newnode(Node *f,int val,int id) {
	Tr[cnt].fa = f;Tr[cnt].val = val;Tr[cnt].id = id;Tr[cnt].sz = 0;Tr[cnt].ch[0] = Tr[cnt].ch[1] = null;return &Tr[cnt++];
}

void Update(Node *u) {
	u -> sz = 1;
	if(u -> ch[0] != null)u -> sz += u -> ch[0] -> sz;
	if(u -> ch[1] != null)u -> sz += u -> ch[1] -> sz;
}

void Rotate(Node *u) {
	Node *x = u -> fa,*y = x -> fa;int v = u == x -> ch[1];
	u -> fa = y;if(y != null)y -> ch[x == y -> ch[1]] = u;
	x -> ch[v] = u -> ch[v^1];if(u -> ch[v^1] != null)u -> ch[v^1] -> fa = x;
	x -> fa = u;u -> ch[v^1] = x;Update(x);
}

void Splay(Node *u,Node *f) {
	Node *x;
	for(;(x = u -> fa) != f;Rotate(u))if(x -> fa != f)Rotate((u == x -> ch[1]) == (x == x -> fa -> ch[1]) ? x : u);
	Update(u);if(f == null)root = u;
}

Node* Find_front(int x) {
	Node *u = root,*ret;int rr = inf+1,tr = -2;
	while(u != null) {
		if(u -> val < x)u = u -> ch[0];
		else {
			if(u -> val < rr || (u -> val == rr && ti[u -> id] > tr)) {
				rr = u -> val;ret = u;tr = ti[u -> id];
			}
			u = u -> ch[1];
		}
	}
	return ret;
}

Node* Find_back(int x) {
	Node *u = root,*ret;int rr = -2,tr = inf+1;
	while(u != null) {
		if(u -> val >= x)u = u -> ch[1];
		else {
			if(u -> val > rr || (u -> val == rr && ti[u -> id] < tr)) {
				rr = u -> val;ret = u;tr = ti[u -> id];
			}
			u = u -> ch[0];
		}
	}
	return ret;
}

Node* Find_front(int x,int t) {
	Node *u = root,*ret;int rr = inf+1,tr = -2;
	while(u != null) {
		if(u -> val == x) {
			if(ti[u -> id] >= t)u = u -> ch[0];
			else {
				if(rr != u -> val || ti[u -> id] > tr) {
					rr = u -> val;
					tr = ti[u -> id];
					ret = u;
				}
				u = u -> ch[1];
			}
		}
		else if(u -> val < x)u = u -> ch[0];
		else {
			if(u -> val < rr || (u -> val == rr && ti[u -> id] > tr)) {
				rr = u -> val;ret = u;tr = ti[u -> id];
			}
			u = u -> ch[1];
		}
	}
	return ret;
}

Node* Find_back(int x,int t) {
	Node *u = root,*ret;int rr = -2,tr = inf+1;
	while(u != null) {
		if(u -> val == x) {
			if(ti[u -> id] <= t)u = u -> ch[1];
			else {
				if(rr != u -> val || ti[u -> id] < tr) {
					rr = u -> val;
					tr = ti[u -> id];
					ret = u;
				}
				u = u -> ch[0];
			}
		}
		else if(u -> val > x)u = u -> ch[1];
		else {
			if(u -> val > rr || (u -> val == rr && ti[u -> id] < tr)) {
				rr = u -> val;ret = u;tr = ti[u -> id];
			}
			u = u -> ch[0];
		}
	}
	return ret;
}

void Insert(Node *u) {
	Node *L = Find_front(u -> val),*R = Find_back(u -> val);
	Splay(R,null);Splay(L,root);root -> ch[0] -> ch[1] = u;
	u -> fa = root -> ch[0];Splay(u,null);
}

Node* Insert(int x,int id) {
	Node *L = Find_front(x),*R = Find_back(x),*u;
	Splay(R,null);Splay(L,root);u = root -> ch[0] -> ch[1] = Newnode(root -> ch[0],x,id);
	Splay(u,null);return u;
}

void Delete(Node *u) {
	Node *L = Find_front(u -> val,ti[u -> id]),*R = Find_back(u -> val,ti[u -> id]);
	Splay(R,null);Splay(L,root);root -> ch[0] -> ch[1] = null;
	Splay(root -> ch[0],null);
}

Node* Find(int x){
	Node *u = root;
	while(u != null) {
		if(u -> ch[0] -> sz + 1 == x)return u;
		if(x <= u -> ch[0] -> sz)u = u -> ch[0];
		else {
			x -= u -> ch[0]-> sz + 1;
			u = u -> ch[1];
		}
	}
}

void init() {
	null = Newnode(null,0,0);root = Newnode(null,inf,0);root -> ch[1] = Newnode(root,-1,0);Update(root -> ch[1]);Update(root);
}

int Insert() {
	int l = strlen(s),now = 0;
	for(int i = 1; i < l; i++) {
		int id = s[i] - 'A',&ch = T[now].ch[id];
		if(!ch)ch = ++Tcnt;
		C[ch] = id;fa[ch] = now;now = ch;
	}
	if(T[now].value)is = true;
	T[now].value = true;
	return now;
}

void print(int u) {
	if(u == 0)return;
	print(fa[u]);
	putchar(C[u]+'A');
}

void Dfs(Node *u) {
	if(u == null)return;
	Dfs(u -> ch[0]);
	print(u -> id);ddcnt--;if(ddcnt)putchar(' ');
	Dfs(u -> ch[1]);
}

int getnum() {
	int ret = 0,l = strlen(s);
	for(int i = 1; i < l; i++) {
		ret = ret * 10 + s[i] - '0';
	}
	return ret;
}

int main() {
	scanf("%d",&n);int x;init();
	for(int i = 1; i <= n; i++) {
		scanf("%s",s);
		if(s[0] == '+') {
			scanf("%d",&x);is = false;
			int r = Insert();
			if(is) {
				Delete(node[r]);node[r] -> val = x;Insert(node[r]);
			}
			else {
				node[r] = Insert(x,r);
			}
			ti[r] = ++ticnt;
		}
		else if(s[0] == '?') {
			if(s[1] >= '0' && s[1] <= '9') {
				int r = getnum(),ret = min(root -> sz,r+11);Node *L = Find(r),*R = Find(ret);
				Splay(R,null);Splay(L,root);ddcnt = ret-r-1;
				Dfs(root -> ch[0] -> ch[1]);
				putchar('\n');
			}
			else {
				int r = Insert();
				Splay(node[r],null);
				printf("%d\n",root -> ch[0] -> sz);
			}
		}
	}
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值