BZOJ 1862: [Zjoi2006]GameZ游戏排名系统 [treap hash]

Posted Candy?

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 1862: [Zjoi2006]GameZ游戏排名系统 [treap hash]相关的知识,希望对你有一定的参考价值。

1862: [Zjoi2006]GameZ游戏排名系统

Time Limit: 5 Sec  Memory Limit: 64 MB
Submit: 1318  Solved: 498
[Submit][Status][Discuss]

Description

GameZ为他们最新推出的游戏开通了一个网站。世界各地的玩家都可以将自己的游戏得分上传到网站上。这样就可以看到自己在世界上的排名。得分越高,排名就越靠前。当两个玩家的名次相同时,先上传记录者优先。由于新游戏的火爆,网站服务器已经难堪重负。为此GameZ雇用了你来帮他们重新开发一套新的核心。排名系统通常要应付三种请求:上传一条新的得分记录、查询某个玩家的当前排名以及返回某个区段内的排名记录。当某个玩家上传自己最新的得分记录时,他原有的得分记录会被删除。为了减轻服务器负担,在返回某个区段内的排名记录时,最多返回10条记录。

Input

第一行是一个整数n(n>=10)表示请求总数目。接下来n行每行包含了一个请求。请求的具体格式如下: +Name Score 上传最新得分记录。Name表示玩家名字,由大写英文字母组成,不超过10个字符。Score为最多8位的正整数。 ?Name 查询玩家排名。该玩家的得分记录必定已经在前面上传。 ?Index 返回自第Index名开始的最多10名玩家名字。Index必定合法,即不小于1,也不大于当前有记录的玩家总数。输入文件总大小不超过2M。 NOTE:用C++的fstream读大规模数据的效率较低

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

复习一下treap
因为同样v先提交排名靠前,所以需要记录时间
v小到大,tm大到小
treap操作变化的地方就是v相同时要讨论时间
插入一个人先在哈希表里找他,然后删除它在插入新的
注意这样的话是倒着排名
 
注意:
1.旋转别写错
2.拷贝字符串memcpy(tar,s,strlen(s))不是sizeof(s)........
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define lc t[x].l
#define rc t[x].r
const int N=250005,MOD=985003;
int read(){
    char c=getchar();int x=0,f=1;
    while(c<0||c>9){if(c==-)f=-1; c=getchar();}
    while(c>=0&&c<=9){x=x*10+c-0; c=getchar();}
    return x*f;
}
int v,tm;
char s[15];
struct node{
    int l,r,v,t,size,rnd;
    char s[15];
}t[N];
int sz,root;
inline void update(int x){t[x].size=t[lc].size+t[rc].size+1;}
inline void rturn(int &x){
    int c=lc;lc=t[c].r;t[c].r=x;
    t[c].size=t[x].size;update(x);x=c;
}
inline void lturn(int &x){
    int c=rc;rc=t[c].l;t[c].l=x;
    t[c].size=t[x].size;update(x);x=c;
}
inline void ins(int &x,int v,int tm,char s[]){
    if(x==0){
        sz++;x=sz;
        t[x].l=t[x].r=0;t[x].size=1;
        t[x].v=v;t[x].rnd=rand();t[x].t=tm;
        memcpy(t[x].s,s,strlen(s));
        return;
    }
    t[x].size++;
    if(v<=t[x].v){
        ins(lc,v,tm,s);
        if(t[lc].rnd<t[x].rnd) rturn(x);
    }else{
        ins(rc,v,tm,s);
        if(t[rc].rnd<t[x].rnd) lturn(x);
    }
}
inline void del(int &x,int v,int tm){
    if(x==0) return;
    if(t[x].v==v){
        if(t[x].t==tm){
            if(lc*rc==0) x=lc+rc;
            else if(t[lc].rnd<t[rc].rnd) rturn(x),del(x,v,tm);
            else lturn(x),del(x,v,tm);
        }else{
            t[x].size--;
            if(tm>t[x].t) del(lc,v,tm);
            else del(rc,v,tm);
        }
    }else{
        t[x].size--;
        if(v<t[x].v) del(lc,v,tm);
        else del(rc,v,tm);
    }
}
int rnk(int x,int v,int tm){
    if(x==0) return 0;
    if(t[x].v==v){
        if(tm==t[x].t) return t[lc].size+1;
        else if(tm>t[x].t) return rnk(lc,v,tm);
        else return t[lc].size+1+rnk(rc,v,tm);
    }
    else if(v<t[x].v) return rnk(lc,v,tm);
    else return t[lc].size+1+rnk(rc,v,tm);
}
int kth(int x,int k){
    if(x==0) return 0;
    if(k<=t[lc].size) return kth(lc,k);
    else if(k>t[lc].size+1) return kth(rc,k-t[lc].size-1);
    else return x;
}

struct data{
    int v,tm,ne;
    char s[15];
}mp[MOD+5];
int h[MOD+5],cnt;
int hsh(char s[]){
    int x=0,len=strlen(s+1);
    for(int i=1;i<=len;i++) x=(x*27+s[i]-A+1)%MOD;
    return x;
}
inline bool equ(char s1[],char s2[]){
    int l1=strlen(s1),l2=strlen(s2);
    if(l1!=l2) return false;
    for(int i=1;i<=l1;i++) if(s1[i]!=s2[i]) return false;
    return true;
}
void Insert(char s[],int v,int tm){
    int k=hsh(s);
    for(int i=h[k];i;i=mp[i].ne){
        if(equ(s,mp[i].s)){
            del(root,mp[i].v,mp[i].tm);
            mp[i].v=v;mp[i].tm=tm;
            ins(root,v,tm,s);
            return;
        }
    }
    cnt++;
    mp[cnt].v=v;mp[cnt].tm=tm;
    memcpy(mp[cnt].s,s,strlen(s));
    mp[cnt].ne=h[k];h[k]=cnt;
    ins(root,v,tm,s);
}
void Rank(char s[]){
    int k=hsh(s),i;
    for(i=h[k];i;i=mp[i].ne)
        if(equ(s,mp[i].s)) break;
    printf("%d\n",cnt+1-rnk(root,mp[i].v,mp[i].tm));
}
void Kth(char s[]){
    int k=0,len=strlen(s+1);
    for(int i=1;i<=len;i++) k=k*10+s[i]-0;
    //printf("Kth %d %s %d\n",k,s,len);
    for(int i=k;i<=cnt&&i<=k+9;i++){
        printf("%s",t[kth(root,cnt+1-i)].s+1);
        if(i<cnt&&i<k+9) putchar( );
    }
    putchar(\n);
}
int main(){
    int T=read();
    for(int i=1;i<=T;i++){
        scanf("%s",s);
        if(s[0]==+){
            v=read();
            Insert(s,v,i);
        }else{
            if(s[1]>=0&&s[1]<=9) Kth(s);
            else Rank(s);
        }
    }
}

 

 

以上是关于BZOJ 1862: [Zjoi2006]GameZ游戏排名系统 [treap hash]的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1862/1056: [Zjoi2006]GameZ游戏排名系统

BZOJ 1003: [ZJOI2006]物流运输trans

「bzoj1003」「ZJOI2006」物流运输 最短路+区间dp

bzoj1003 [ZJOI2006]物流运输

bzoj1003[ZJOI2006]物流运输

bzoj1003: [ZJOI2006]物流运输