1056: [HAOI2008]排名系统
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1822 Solved: 496
[ Submit][ Status][ Discuss]
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的排名
+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
CATHY TOM ADAM BOB
CATHY LEO KAINE WALT MICK GRACE SANDY JACK TOM BOB
WALT MICK GRACE SANDY JACK TOM BOB ADAM DAM
4
HINT
100%数据满足N<=250000
显然题目要你维护一颗排名树。。
把每个人的名字转换成27进制然后treap瞎搞一通。。。
为什么27进制呢。。。
因为离散化后想用1~26来表示,如果用26进制0~25里面的0(A)不好判断。。。
<strong><span style="font-size:18px;">#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 250000+10;
typedef long long LL;
int n,i,j,S[maxn],t[maxn],cur = 0,New,tail = 0,TOT = 0,END;
LL sorta[maxn];
bool vis[maxn];
struct Q{
char flag,nam[15];
int sco;
}query[maxn];
class data{
private:
struct Node{
int pri,siz,num,sco;
Node *ch[2];
}*root,*tot,pool[maxn];
void maintain(Node *&x) {
x->siz = 1;
for (int l = 0; l <= 1; l++)
if (x->ch[l] != NULL) x->siz += x->ch[l]->siz;
}
void rotate(Node *&x,int d) {
Node *y = x->ch[d];
x->ch[d] = y->ch[d^1]; maintain(x);
y->ch[d^1] = x;
x = y; maintain(x);
}
int cmp(Node *x,int Num) {
if (x->sco < S[Num]) return 0;
if (x->sco > S[Num]) return 1;
if (t[x->num] < t[Num]) return 1;
return 0;
}
void Insert(Node *&x,int sco,int pri,int num) {
if (x == NULL) {
x = tot++;
x->sco = sco; x->pri = pri; x->num = num;
x->ch[0] = NULL; x->ch[1] = NULL; x->siz = 1;
return;
}
int d = cmp(x,num);
Insert(x->ch[d],sco,pri,num);
maintain(x);
if (x->ch[d]->pri > x->pri) rotate(x,d);
}
void Remove(Node *&x,int num) {
if (x->num == num) {
if (x->ch[0] == NULL && x->ch[1] == NULL) {
x = NULL; return;
}
for (int l = 0; l <= 1; l++)
if (x->ch[l] == NULL) {
x = x->ch[l^1]; return;
}
int d1 = x->ch[0]->pri > x->ch[1]->pri?0:1;
rotate(x,d1);
Remove(x->ch[d1^1],num);
if (x != NULL) maintain(x);
return;
}
int d = cmp(x,num);
Remove(x->ch[d],num);
if (x != NULL) maintain(x);
}
int Lower_Bound(Node *x,int Num) {
for (;;) {
int d = 1;
if (x->ch[0] != NULL) d += x->ch[0]->siz;
if (d == Num) return x->num;
if (d > Num) x = x->ch[0];
else {
Num -= d;
x = x->ch[1];
}
}
}
int find_rank(Node *x,int num) {
int ret = 0;
for (;;) {
int d = cmp(x,num);
if (x->num == num) {
if (x->ch[0] != NULL)
ret += x->ch[0]->siz;
return ret+1;
}
if (d) {
++ret;
if (x->ch[0] != NULL) ret += x->ch[0]->siz;
x = x->ch[1];
}
else x = x->ch[0];
}
}
public:
data(){root = NULL; tot = pool;}
void Ins(int num,int sco) {
Insert(root,sco,rand(),num);
}
void Rem(int num) {
Remove(root,num);
}
int L_B(int num) {
return Lower_Bound(root,num);
}
int F_R(int num) {
return find_rank(root,num);
}
};
char get_com()
{
char ret = 0;
while (ret != '+' && ret != '?') ret = getchar();
return ret;
}
LL get_num(int pos)
{
LL ret = 0,x = 1;
int len = strlen(query[pos].nam);
for (int l = 0; l < len; l++) {
ret = ret + 1LL*(query[pos].nam[l]-'A'+1)*x;
x *= 27;
}
return ret;
}
void pri(int pos)
{
LL out = sorta[pos];
for (; out; out /= 27LL) printf("%c",out%27LL+'A'-1);
if (i != END) printf(" ");
}
int main()
{
#ifdef YZY
freopen("yzy.txt","r",stdin);
#endif
cin >> n;
static data tree;
tree.Ins(0,-2E9);
for (i = 0; i < n; i++) {
query[i].flag = get_com();
scanf("%s",&query[i].nam);
if (query[i].flag == '+') {
int sco; scanf("%d",&query[i].sco);
sorta[++TOT] = get_num(i);
}
}
sort(sorta+1,sorta+TOT+1);
j = TOT; TOT = 1;
for (i = 2; i <= j; i++)
if (sorta[i] != sorta[i-1])
sorta[++TOT] = sorta[i];
for (j = 0; j < n; j++) {
if (query[j].flag == '+') {
LL N = get_num(j);
int num = lower_bound(sorta + 1,sorta + TOT + 1,N) - sorta;
if (vis[num]) tree.Rem(num);
if (!vis[num]) vis[num] = 1,++cur;
S[num] = query[j].sco; t[num] = j;
tree.Ins(num,query[j].sco);
}
else {
if (query[j].nam[0] >= '0' && query[j].nam[0] <= '9') {
int num = 0,len = strlen(query[j].nam);
for (i = 0; i < len; i++) num = num*10 + query[j].nam[i]-'0';
END = num+9<=cur?num+9:cur;
for (i = num; i <= END; i++)
pri(tree.L_B(i));
printf("\n");
}
else {
LL num = get_num(j);
int N = lower_bound(sorta + 1,sorta + TOT + 1,num) - sorta;
printf("%d\n",tree.F_R(N));
}
}
}
return 0;
}</span></strong>