1. 程式人生 > >[BZOJ1862/Luogu2584][ZJOI2006]GameZ遊戲排名系統

[BZOJ1862/Luogu2584][ZJOI2006]GameZ遊戲排名系統

題目連結:

BZOJ1862

Luogu2584

就是一個裸的平衡樹題。

寫了一顆\(Splay\)

對於分數的覆蓋,可以開\(std::map\)建立對映關係。

可能這個原因常數太大了,\(Luogu\ A\)了,\(BZOJ\)\(O2\)也過不去。。

一定是BZOJ太慢了

#include <map>
#include <cstdio>
#include <cctype>
#include <string>
#include <iostream>

inline char Getop()
{
    register char c=getchar();
    while(c!='+'&&c!='?')c=getchar();
    return c;
}

inline long long Getll()
{
    register long long x=0;
    register char c;
    while(!isdigit(c=getchar()));
    for(;isdigit(c);c=getchar())x=(x<<3)+(x<<1)+(c^48);
    return x;
}

inline void Putint(int x)
{
    register char Sta[15];
    register int Top=13;
    register char f=true;
    if(x<0)f=false,x=-x;
    for(Sta[13]='\n',Sta[14]=0;Top==13||x;x/=10)Sta[--Top]=x%10^48;
    if(!f)Sta[--Top]='-';
    fwrite(Sta+Top,1,14-Top,stdout);
}

struct Splay_Tree
{
    int Root,Nodn,TSiz;
    int Fa[250005];
    int Siz[250005];
    int Son[250005][2];
    long long Val[250005];
    std::map<long long,std::string> Nams;
    std::map<std::string,long long> Scos;

    inline void Update(int x)
    {
        if(!x)return;
        Siz[x]=1+Siz[Son[x][0]]+Siz[Son[x][1]];
    }

    inline int Relation(int x)
    {
        return Son[Fa[x]][1]==x;
    }

    inline void Rotate(int x)
    {
        int x_Fa=Fa[x],x_Fa2=Fa[x_Fa],Relat=Relation(x);
        Son[x_Fa][Relat]=Son[x][Relat^1];
        Fa[Son[x][Relat^1]]=x_Fa;
        Son[x][Relat^1]=x_Fa;
        Fa[x_Fa]=x;
        Fa[x]=x_Fa2;
        if(x_Fa2)Son[x_Fa2][Son[x_Fa2][1]==x_Fa]=x;
        Update(x_Fa),Update(x);
    }

    inline void Splay(int x)
    {
        for(register int x_Fa;x_Fa=Fa[x];Rotate(x))
            if(Fa[x_Fa])
                if(Relation(x)==Relation(x_Fa))Rotate(x_Fa);
                else Rotate(x);
        Root=x;
    }

    inline void Clear_Node(int x)
    {
        Son[x][0]=Son[x][1]=Fa[x]=Siz[x]=Val[x]=0;
    }

    inline void ToRoot(long long x)
    {
        for(register int Pos=Root;true;)
            if(x==Val[Pos])return Splay(Pos);
            else Pos=Son[Pos][x>Val[Pos]];
    }

    inline void Delete(std::string x)
    {
        --TSiz;
        ToRoot(Scos[x]);
        Nams.erase(Scos[x]);
        Scos.erase(x);
        if(!Son[Root][0]&&!Son[Root][1])return Clear_Node(Root);
        if(!Son[Root][0])
        {
            int Tmp=Root;
            Fa[Root=Son[Root][1]]=0;
            return Clear_Node(Tmp);
        }
        if(!Son[Root][1])
        {
            int Tmp=Root;
            Fa[Root=Son[Root][0]]=0;
            return Clear_Node(Tmp);
        }
        int Pre=Son[Root][0],Tmp=Root;
        while(Son[Pre][1])Pre=Son[Pre][1];
        Splay(Pre);
        Son[Root][1]=Son[Tmp][1];
        Fa[Son[Tmp][1]]=Root;
        Clear_Node(Tmp);
        Update(Root);
    }

    inline void Insert(long long x,std::string s)
    {
        ++TSiz;
        if(Scos.find(s)!=Scos.end())Delete(s);
        Nams[x]=s;
        Scos[s]=x;
        if(TSiz==1)
        {
            Root=++Nodn;
            Son[Root][0]=Son[Root][1]=Fa[Root]=0;
            Siz[Root]=1;
            Val[Root]=x;
            return;
        }
        for(register int Pos=Root,P_Fa=0;true;)
        {
            P_Fa=Pos;
            Pos=Son[Pos][x>Val[Pos]];
            if(!Pos)
            {
                ++Nodn;
                Son[Nodn][0]=Son[Nodn][1]=0;
                Fa[Nodn]=P_Fa;
                Siz[Nodn]=1;
                Son[P_Fa][x>Val[P_Fa]]=Nodn;
                Val[Nodn]=x;
                Update(P_Fa);
                return Splay(Nodn);
            }
        }
    }

    inline long long Get_Score_By_Rank(int x)
    {
        for(register int Pos=Root;true;)
            if(Siz[Son[Pos][0]]+1==x){Splay(Pos);return Val[Pos];}
            else if(Siz[Son[Pos][0]]>=x)Pos=Son[Pos][0];
            else x-=Siz[Son[Pos][0]]+1,Pos=Son[Pos][1];
    }

    inline int Query(std::string s)
    {
        ToRoot(Scos[s]);
        return Siz[Son[Root][1]]+1;
    }

    inline void Foreach(long long x)
    {
        register std::map<long long,std::string>::iterator it=Nams.find(Get_Score_By_Rank(TSiz-x+1));
        for(register int i=1;i<=10&&it!=Nams.end();++i,--it)
        {
            if(i!=1)putchar(' ');
            printf("%s",(*it).second.c_str());
            if(it==Nams.begin())break;
        }
        puts("");
    }

    inline void Debug()
    {
        for(register int i=1;i<=Nodn;++i)
            printf("%d %d %d %d %lld\n",Fa[i],Siz[i],Son[i][0],Son[i][1],Val[i]);
    }
}Tree;

int n;

int main()
{
    scanf("%d",&n);
    for(register int i=1;i<=n;++i)
    {
        char op=Getop();
        std::string Name;
        if(op=='+')
        {
            std::cin>>Name;
            long long Score=Getll()*1000000LL+n-i;
            Tree.Insert(Score,Name);
        }
        else
        {
            char s[15];
            scanf("%s",s+1);
            if(isdigit(s[1]))
            {
                long long Rank=0;
                for(register int i=1;s[i];++i)Rank=(Rank<<3)+(Rank<<1)+(s[i]^48);
                Tree.Foreach(Rank);
            }
            else
            {
                for(register int i=1;s[i];++i)Name.push_back(s[i]);
                Putint(Tree.Query(Name));
            }
        }
    }
    return 0;
}