bzoj1862&&1056 GameZ游戏排名系统 treap+哈希表

7 篇文章 0 订阅
1 篇文章 0 订阅

居然只是隔了就拿来当原题,这样真的好吗=。=
平衡树直接硬上,然后用哈希表存一下名字,其余的话就是裸操作了,要注意的是要加上一个时间标记,不然删的时候会炸。。
时间标记有几个地方忘记加上结果T了半天= =。
码了1个小时多,手酸了都= =4400B

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
using namespace std;
const int N=250001;
const int mo=985003;
struct treap
{
    int v,s,l,r,time,rnd;
    char ch[10];
};
int n,m,sz,root,tot,head[mo+1];
struct data1
{
    int v,time,next;
    char ch[10];
}hash[N];
treap t[N];
bool cmp(char a[],char b[])
{
    for(int i=1;i<max(strlen(a),strlen(b));i++)
    if (a[i]!=b[i])return 0;
    return 1;
}
inline int Hash(char ch[])
{
    int s=0;
    for(int i=1;i<strlen(ch);i++)
    {
        s*=27;
        s+=ch[i]-'A'+1;
        s%=mo;
    }
    return s;
}
inline void rtl(int &x)
{
    int y=t[x].r;
    t[x].r=t[y].l;
    t[y].l=x;
    t[y].s=t[x].s;
    t[x].s=t[t[x].l].s+t[t[x].r].s+1;
    x=y;
}
inline void rtr(int &x)
{
    int y=t[x].l;
    t[x].l=t[y].r;
    t[y].r=x;
    t[y].s=t[x].s;
    t[x].s=t[t[x].l].s+t[t[x].r].s+1;
    x=y;
}
inline void del(int &k,int x,int time)
{
    if (t[k].v==x)
    {
        if (t[k].time==time)
        {
            if (t[k].l*t[k].r==0)k=t[k].l+t[k].r;
            else if (t[t[k].l].rnd<t[t[k].r].rnd){rtr(k),del(k,x,time);}
            else {rtl(k),del(k,x,time);}
        }
        else if (time>t[k].time)
        {
            t[k].s--;
            del(t[k].l,x,time);
        }
        else
        {
            t[k].s--;
            del(t[k].r,x,time);
        }
    }
    else if (x<t[k].v)
        {
            t[k].s--;
            del(t[k].l,x,time);
        }
        else
        {
            t[k].s--;
            del(t[k].r,x,time);
        }
}
inline void ins(int &k,char ch[],int x,int time)
{
    if (!k)
    {
        sz++;
        k=sz;t[k].v=x;
        t[k].s=1;
        t[k].rnd=rand();
        t[k].time=time;
        memcpy(t[k].ch,ch,strlen(ch));
        return;
    }
    t[k].s++;
    if (x<=t[k].v)
    {
        ins(t[k].l,ch,x,time);
        if (t[t[k].l].rnd<t[k].rnd)rtr(k);
    }
    else
    {
        ins(t[k].r,ch,x,time);
        if (t[t[k].r].rnd<t[k].rnd)rtl(k);
    }
}
inline void INS(char ch[],int x,int time)
{
    int k=Hash(ch);
    for(int i=head[k];i;i=hash[i].next)
    {
        if (cmp(hash[i].ch,ch))
        {
            del(root,hash[i].v,hash[i].time);
            hash[i].time=time;
            hash[i].v=x;
            ins(root,ch,x,time);
            return;
        }
    }
    tot++;
    hash[tot].time=time;
    hash[tot].v=x;
    memcpy(hash[tot].ch,ch,strlen(ch));
    hash[tot].next=head[k];
    head[k]=tot;
    ins(root,ch,x,time);
}
inline int get(char ch[])
{
    int k=Hash(ch);
    for(int i=head[k];i;i=hash[i].next)
    {
        if (cmp(hash[i].ch,ch))return i;
    }
}
inline int getrank(int k,int x,int time)
{
    if (!k)return 0;
    if (t[k].v==x)
    {
        if (t[k].time>time)return getrank(t[k].r,x,time);
        else if (t[k].time<time)return 1+t[t[k].r].s+getrank(t[k].l,x,time);
        else return t[t[k].r].s+1;
    }
    else if (t[k].v<x)return getrank(t[k].r,x,time);
    else return 1+t[t[k].r].s+getrank(t[k].l,x,time);
}
inline void ask1(char ch[])
{
    int t=get(ch);
    printf("%d\n",getrank(root,hash[t].v,hash[t].time));
}
inline int index(int k,int x)
{
    if (t[t[k].r].s+1==x)return k;
    else if (x<=t[t[k].r].s)return index(t[k].r,x);
    else return index(t[k].l,x-t[t[k].r].s-1);
}
inline void ask2(char ch[])
{
    int s=0;
    for(int i=1;i<strlen(ch);i++){s*=10;s+=ch[i]-'0';}
    for(int i=s;i<=tot&&i<=s+9;i++)
    {
        printf("%s",t[index(root,i)].ch+1);
        if (i<tot&&i<s+9)printf(" ");
    }
    printf("\n");
}
int main()
{
    scanf("%d",&n);
    char ch[11];
    int x;
    for(int i=1;i<=n;i++)
    {
        scanf("%s",ch);
        if (ch[0]=='+')
        {
            scanf("%d",&x);
            INS(ch,x,i);
        }
        else if (ch[1]<='Z'&&ch[1]>='A')ask1(ch);
        else ask2(ch);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值