[BZOJ1862/Luogu2584][ZJOI2006]GameZ遊戲排名系統
阿新 • • 發佈:2018-12-23
題目連結:
就是一個裸的平衡樹題。
寫了一顆\(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; }