[bzoj1056] [HAOI2008]排名系统

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

Solution

平衡树模板题。。

因为我太懒了字符串哈希直接\(map\)就好了。

#include<bits/stdc++.h>
using namespace std;

#define int long long 

void read(int &x) {
    x=0;int f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}
 
void print(int x) {
    if(x<0) putchar('-'),x=-x;
    if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');}

const int maxn = 5e5+10;
const int base = 29;
const int inf = 1e18;

char s[20];
int tot=2;
map<string,int > mp;

int hs() {
	int r=strlen(s+1);string ss="";
	for(int i=1;i<=r;i++) ss+=s[i];
	return mp[ss]?mp[ss]:mp[ss]=++tot;
}

char name[maxn][12];
int cnt,fa[maxn],son[maxn][2],sz[maxn],val[maxn],rt,vis[maxn],n;

void update(int x) {sz[x]=sz[son[x][0]]+sz[son[x][1]]+1;}

int which(int x) {return son[fa[x]][1]==x;}

void rotate(int x,int &aim) {
	int y=fa[x],z=fa[y],ww=which(x);
	if(y==aim) aim=x;
	else son[z][son[z][1]==y]=x;
	fa[x]=z,fa[y]=x,fa[son[x][ww^1]]=y;
	son[y][ww]=son[x][ww^1],son[x][ww^1]=y;
	update(y),update(x);
}

void splay(int x,int &aim) {
	while(x!=aim) {
		int y=fa[x],z=fa[y];
		if(y!=aim) rotate(((son[y][1]==x)^(son[z][1]==y))?x:y,aim);
		rotate(x,aim);
	}
}

void insert(int &p,int x,int f) {
	if(!p) {fa[x]=f,sz[x]=1,p=x;splay(x,rt);return ;}
	if(val[x]>val[p]) insert(son[p][1],x,p);
	else insert(son[p][0],x,p);
}

void del(int x) {
	splay(x,rt);int pre=son[x][0],nxt=son[x][1];
	while(son[pre][1]) pre=son[pre][1];
	while(son[nxt][0]) nxt=son[nxt][0];
	splay(pre,rt),splay(nxt,son[rt][1]);
	son[nxt][0]=fa[x]=0;update(nxt),update(pre);
}

int get_rk(int x) {splay(x,rt);return sz[son[x][1]];}

void dfs(int x) {
	if(son[x][1]) dfs(son[x][1]);
	printf("%s ",name[vis[x]]+1);
	if(son[x][0]) dfs(son[x][0]);
}

int find(int x,int k) {
	if(sz[son[x][0]]>=k) return find(son[x][0],k);
	else if(sz[son[x][0]]+1==k) return x;
	else return find(son[x][1],k-sz[son[x][0]]-1);
}

void solve(int l,int r) {
	splay(find(rt,l-1),rt),splay(find(rt,r+1),son[rt][1]);
	dfs(son[son[rt][1]][0]);
}

signed main() {
	int m;read(m);
	val[1]=-inf;insert(rt,1,0);
	val[maxn-1]=inf;insert(rt,maxn-1,0);
	for(int cas=1;cas<=m;cas++) {
		memset(s,0,sizeof s);
		char c=getchar();
		while(c=='\n'||c==' ') c=getchar();
		if(c=='+') {
			scanf("%s",s+1);int x,v,r=strlen(s+1);read(v);s[r+1]=0;
			if(vis[x=hs()]) del(x);val[x]=v;insert(rt,x,0);
			if(!vis[x]) {vis[x]=++cnt;n++;for(int i=1;i<=r;i++) name[cnt][i]=s[i];}
		} else {
			c=getchar();int top=0;
			while(c!='\n'&&c!=' '&&c!=EOF) s[++top]=c,c=getchar();
			if(isdigit(s[1])) {
				int x=0;
				for(int i=1;i<=top;i++) x=x*10+s[i]-'0';
				solve(n-min(n,x+9)+2,n-x+2);puts("");
			} else write(get_rk(hs()));
		}
	}
	return 0;
}
posted @ 2019-02-18 11:41  Hyscere  阅读(183)  评论(0编辑  收藏  举报