[BZOJ1862/Luogu2584][ZJOI2006]GameZ游戏排名系统
题目链接:
就是一个裸的平衡树题。
写了一颗\(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;
}