BZOJ-1056/1862: [HAOI2008]排名系统

[文章目录]

Decription

排名系统通常要应付三种请求:上传一条新的得分记录、查询某个玩家的当前排名以及返回某个区段内的排名记录。当某个玩家上传自己最新的得分记录时,他原有的得分记录会被删除。为了减轻服务器负担,在返回某个区段内的排名记录时,最多返回10条记录。N<=250000

splay+hash表。
指针版splay写的越来越顺手了,估计改不了了吧,get了hash表新技能。写一个bool的check,然后计数器为字符串id,hash值为head下标,然后直接扫,check匹配,遇到新的string就hash挂链,链式前向星直接上。
另外check的时候传参(char st1[],char st2[])||(char *st1,*st2)实测快慢没差多少。
另外字符串复制,用到库里的memcpy()函数。用法为(char st1[],char st2[],int y),表示将st2指针位置开始的y个字符复制到st1开始的y个位置上。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n,tot,num=2;
//=======================================================hash
char nam[251000][11],st[15];
int head[1001000],to_id[251000],nxt[251000],cnt;
bool check(char *st1,char *st2)
{
    int l1=strlen(st1),l2=strlen(st2);
    if(l1!=l2) return false;
    for(int i=0;i<l1;i++) if(st1[i]!=st2[i]) return false;
    return true;
}
int hash_id(char *str)
{
    int len=strlen(str),re=0;
    for(int i=1;i<len;i++) re=(re*97+str[i])%1000003;
    return re;
}
void add(int x,int y) {to_id[++cnt]=y; nxt[cnt]=head[x]; head[x]=cnt;}
//=======================================================splay
struct node
{
    node *fa,*c[2];
    int w,siz,id;
    node(int x,int y);
    void pushup(){siz=c[0]->siz+c[1]->siz+1;}
}*null=new node(0,0),*root,*a[251000];
node :: node(int x,int y) {fa=c[1]=c[0]=null; siz=null?1:0; w=x; id=y;}
void initialize()
{
    root=new node(0x80000000,0);
    root->c[1]=new node(0x7fffffff,0);
    root->c[1]->fa=root;
    root->pushup();
}
void rotate(node *x)
{
    node *y=x->fa; bool l=(x==y->c[1]),r=l^1;
    y->c[l]=x->c[r]; x->c[r]->fa=y;
    x->c[r]=y; x->fa=y->fa;
    if(y==y->fa->c[0]) y->fa->c[0]=x;
    else y->fa->c[1]=x;
    y->fa=x; y->pushup(); x->pushup();
    if(y==root)  root=x;
}
void splay(node *x,node *tar)
{
    while(x->fa!=tar)
    {
        node *y=x->fa,*z=y->fa;
        if(z==tar){rotate(x); break;}
        if((x==y->c[0])^(y==z->c[0])==0) rotate(y);
        else rotate(x); rotate(x);
    }
}
void insert(node *x)
{
    node *l,*r,*p=root; int sw=x->w;
    while(p!=null)
    {
        if(p->w<sw) l=p,p=p->c[1];
        else r=p,p=p->c[0];
    }
    splay(l,null); splay(r,root);
    root->c[1]->c[0]=x; x->fa=root->c[1];
    root->c[1]->pushup(); root->pushup();
}
int z[20],top;
void output(node *x)
{
    if(x==null) return;
    output(x->c[1]);
    z[++top]=x->id;
    output(x->c[0]);
}
void find(node *x,int y,node *z)
{
    while(1)
    {
        int tmp=x->c[0]->siz;
        if(y<=tmp) x=x->c[0];
        else
        {
            y-=(tmp+1);
            if(!y) break;
            x=x->c[1];
        }
    }
    splay(x,z);
}
void del(node *x)
{
    node *l=x,*r=x;
    if(l->c[0]!=null) {l=l->c[0]; while(l->c[1]!=null) l=l->c[1];}
    else {while(l==l->fa->c[0]) l=l->fa; l=l->fa;}
    if(r->c[1]!=null) {r=r->c[1]; while(r->c[0]!=null) r=r->c[0];}
    else {while(r==r->fa->c[1]) r=r->fa; r=r->fa;}
    splay(l,null); splay(r,root);
    root->c[1]->c[0]=null;
    root->c[1]->pushup();
    root->pushup();
    free(x);
}
//=======================================================end
void Insert()
{
    int id=hash_id(st+1),x,y=-1; scanf("%d",&x);
    for(int i=head[id];i;i=nxt[i])
        if(check(nam[to_id[i]],st+1))
            {y=to_id[i];break;}
    if(y==-1)
    {
        ++tot; add(id,tot); memcpy(nam[tot],st+1,strlen(st+1));
        a[tot]=new node(x,tot);
        insert(a[tot]); num++;
    }
    else
    {
        del(a[y]);
        a[y]=new node(x,y);
        insert(a[y]);
    }
}
void Index()
{
    int len=strlen(st+1),x=0;
    for(int i=1;i<=len;i++)
        x=(x<<1)+(x<<3)+st[i]-'0';
    find(root,max(num-x-10,1),null);
    find(root,num-x+1,root);
    top=0; output(root->c[1]->c[0]);
    for(int i=1;i<=top;i++)
        printf("%s%c",nam[z[i]],(i==top)?'\n':' ');
}
void Q_name()
{
    int id=hash_id(st+1),x,tmp=0;
    for(int i=head[id];i;i=nxt[i])
        if(check(nam[to_id[i]],st+1))
            {x=to_id[i]; break;}
    node *p=a[x];
    if(p->c[1]!=null) tmp+=p->c[1]->siz;
    while(p!=root)
    {
        if(p==p->fa->c[0]) tmp+=p->fa->c[1]->siz+1;
        p=p->fa;
    } 
    printf("%d\n",tmp);
}
int main()
{
    initialize();
    scanf("%d",&n);
    while(n--)
    {
        scanf("%s",st);
        if(st[0]=='+') Insert();
        else if(st[1]<'A'||st[1]>'Z') Index();
        else Q_name();
    }
    return 0;
}

发表评论

邮箱地址不会被公开。 必填项已用*标注