刷题集--GameZ游戏排名系统

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

也是一棵无旋treap就秒的。。

#pragma GCC optimize(3,"inline","Ofast")
#include<bits/stdc++.h>
using namespace std;
map<string,int>name;
struct gg{
    int w,ls,rs,rnd,fa,sz;
}node[250010];
int tot=0,root;bool vis[250010];
char idx[250010][15],s[15];
int get_name()
{
    int n=strlen(s);string nw="";
    for(int i=0;i<n;i++)nw+=s[i];
    if(name[nw])return name[nw];
    ++tot;for(int i=0;i<n;i++)idx[tot][i]=s[i];
    idx[tot][n]='\0';
    return name[nw]=tot;
}
int get_int()
{
    int n=strlen(s),res=0;
    for(int i=0;i<n;i++)
        res=res*10+s[i]-48;
    return res;
}
void push_up(int x)
{
    node[x].fa=0;
    node[x].sz=node[node[x].ls].sz+node[node[x].rs].sz+1;
    node[node[x].ls].fa=x,node[node[x].rs].fa=x;
}
int mg(int a,int b)
{
    if(!a||!b)return a+b;
    if(node[a].rnd<=node[b].rnd)
    {
        node[a].rs=mg(node[a].rs,b);
        push_up(a);
        return a;
    }
    else
    {
        node[b].ls=mg(a,node[b].ls);
        push_up(b);
        return b;
    }
}
void split1(int nw,int k,int &x,int &y)
{
    if(!nw)x=y=0;
    else
    {
        if(node[node[nw].ls].sz>=k)y=nw,split1(node[nw].ls,k,x,node[nw].ls);
        else x=nw,split1(node[nw].rs,k-node[node[nw].ls].sz-1,node[nw].rs,y);
        push_up(nw);
    }
}
void split2(int nw,int k,int &x,int &y)
{
    if(!nw)x=y=0;
    else
    {
        if(node[nw].w>=k)x=nw,split2(node[nw].rs,k,node[nw].rs,y);
        else y=nw,split2(node[nw].ls,k,x,node[nw].ls);
        push_up(nw);
    }
}
int rnk(int x)
{
    int res=0;
    res+=node[node[x].ls].sz;
    while(node[x].fa!=0)
    {
        if(node[node[x].fa].rs==x)x=node[x].fa,res+=node[node[x].ls].sz+1;
        else x=node[x].fa;
    }
    return res;
}
void cg(int ps,int w)
{
    //cout<<ps<<" "<<w<<endl;
    int x,y,z;
    if(vis[ps])
    {
        split1(root,rnk(ps),x,y);
        split1(y,1,y,z);
        root=mg(x,z);
    }
    node[ps].fa=0;
    if(!vis[ps])node[ps].rnd=rand();
    node[ps].ls=node[ps].rs=0;
    node[ps].sz=1,node[ps].w=w;
    split2(root,w,x,y);//cout<<root<<" "<<w<<" "<<x<<" "<<y<<endl;
    root=mg(mg(x,ps),y);
    vis[ps]=1;
}
int print(int x)
{
    if(node[x].ls)print(node[x].ls);
    printf("%s ",idx[x]);
    if(node[x].rs)print(node[x].rs);
}
void query(int x)
{printf("%d\n",rnk(x)+1);}
void ask(int ps)
{
    int x,y,z;
    split1(root,ps-1,x,y);
    split1(y,10,y,z);
    print(y);puts("");
    root=mg(x,mg(y,z));
}
int main()
{
    srand(19260817);
    int n,nw,who;char op;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf(" %c",&op);
        if(op=='+')
        {
            scanf("%s",s);
            who=get_name();
            scanf("%d",&nw);
            cg(who,nw);
        }
        else
        {
            scanf("%s",s);
            if(s[0]>='0'&&s[0]<='9')nw=get_int(),ask(nw);
            else
            {
                who=get_name();
                query(who);
            }
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值