1056: [HAOI2008]排名系统

1056: [HAOI2008]排名系统

Time Limit: 10 Sec   Memory Limit: 162 MB
Submit: 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的排名

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

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>


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值