神奇脑洞题解——HAOI[2008]排名系统
这是一道人种检测题!
为啥说他是人种检测题呢,因为官方标算是有随机数的参与的,至于在哪,下面再说。
[HAOI2008] 排名系统
★★★☆ 输入文件:rank.in
输出文件:rank.out
简单对比
时间限制:1 s
内存限制:128 MB
[题目描述]
排名系统通常要应付三种请求:上传一条新的得分记录、查询某个玩家的当前排名以及返回某个区段内的排名记录。当某个玩家上传自己最新的得分记录时,他原有的得分记录会被删除。为了减轻服务器负担,在返回某个区段内的排名记录时,最多返回10条记录。
[输入]
第一行是一个整数n(10<=n<=250000)表示请求总数目。接下来n行,每行包含了一个请求。请求的具体格式如下:
+Name Score 上传最新得分记录。Name表示玩家名字,由大写英文字母组成,不超过10个字符。Score为最多8位的正整数。
?Name 查询玩家排名。该玩家的得分记录必定已经在前面上传。如果两个玩家的得分相同,则先得到该得分的玩家排在前面。
?Index 返回自第Index名开始的最多10名玩家名字。Index必定合法,即不小于1,也不大于当前有记录的玩家总数。
[输出]
对于?Name格式的请求,应输出一个整数表示该玩家当前的排名。
对于?Index格式的请求,应在一行中依次输出从第Index名开始的最多10名玩家姓名,用一个空格分隔。
[样例]
Input
20
+ADAM 1000000
+BOB 1000000
+TOM 2000000
+CATHY 10000000
?TOM
?1
+DAM 100000
+BOB 1200000
+ADAM 900000
+FRANK 12340000
+LEO 9000000
+KAINE 9000000
+GRACE 8000000
+WALT 9000000
+SANDY 8000000
+MICK 9000000
+JACK 7320000
?2
?5
?KAINE
Output
2
CATHY TOM ADAM BOB
CATHY LEO KAINE WALT MICK GRACE SANDY JACK TOM BOB
WALT MICK GRACE SANDY JACK TOM BOB ADAM DAM
4
说明
+ADAM 1000000 加入ADAM的得分记录
+BOB 1000000 加入BOB的得分记录
+TOM 2000000 加入TOM的得分记录
+CATHY 10000000 加入CATHY的得分记录
?TOM 输出TOM目前排名
?1 目前有记录的玩家总数为4,因此应输出第1名到第4名。
+DAM 100000 加入DAM的得分记录
+BOB 1200000 更新BOB的得分记录
+ADAM 900000 更新ADAM的得分记录(即使比原来的差)
+FRANK 12340000 加入FRANK的得分记录
+LEO 9000000 加入LEO的得分记录
+KAINE 9000000 加入KAINE的得分记录
+GRACE 8000000 加入GRACE的得分记录
+WALT 9000000 加入WALT的得分记录
+SANDY 8000000 加入SANDY的得分记录
+MICK 9000000 加入MICK的得分记录
+JACK 7320000 加入JACK的得分记录
?2 目前有记录的玩家总数为12,因此应输出第2名到第11名。
?5 输出第5名到第13名。
?KAINE 输出KAINE的排名
[数据范围]
20%数据满足N<=100
100%数据满足N<=250000
这道题一看就知道是Splay维护得分,至于如何替换?
不换,把原来的得分记录删掉,直接新加进去一个得分即可(同时储存每个人对应最新一次得分记录的序号)
至于字符串处理问题吗,用Map直接压一下即可。
然后强调一下插入的问题,这道题是没有同分维护的,也就是说即使有相同的得分也要再开一个新点。
这个新点一定要开到得分相同点的左儿子上。
因为查询的时候要求同分情况下优先输出最先压入的,这样就可以保证查询时一定按照压入顺序输出。
人种测试:
这道题的官方题解中是有随机化提根的(就是在某个时刻将Splay的形状改变,将根变为某个随机的点)
这个时刻和提出哪个点都是你自己定的,毕竟提根也是有时间的,提的多了亏了,提的少了没用,还有可能随机数提根将树提成链的
非洲福利:根据本人无限次非酋,每200个操作提一次根,提根直接用rand()%tot+1作为被提起的根即可,不要加srand(time(0))。
因为一旦加上time以当前时间作为种子,rand的值就是动态的了。这也就是决定非欧的空间。
#include<iostream> #include<cstdio> #include<map> #include<algorithm> #include<ctime> using namespace std; struct PE { int ff,val,size,ch[2]; }; PE t[2500100]; map<string,int> M; string name[2500100]; int rt,tot,n; string x1,x2; void pushup(int x) { t[x].size=t[t[x].ch[0]].size+1+t[t[x].ch[1]].size; } void rotate(int x) { int y=t[x].ff; int z=t[y].ff; int k=(t[y].ch[1]==x); t[z].ch[y==t[z].ch[1]]=x; t[y].ch[k]=t[x].ch[k^1]; t[t[x].ch[k^1]].ff=y; t[x].ch[k^1]=y; t[y].ff=x; t[x].ff=z; pushup(y); pushup(x); } void Splay(int x,int goal) { while(t[x].ff!=goal) { int y=t[x].ff; int z=t[y].ff; if(z!=goal) { (t[y].ch[0]==x)^(t[z].ch[0]==y)?rotate(x):rotate(y); } rotate(x); } if(goal==0) rt=x; } void insert(int x,int id) { int u=rt; while(t[u].ch[x>t[u].val]) { u=t[u].ch[x>t[u].val]; } t[id].ff=u; t[id].val=x; t[id].ch[0]=t[id].ch[1]=0; t[id].size=1; t[u].ch[t[u].val<x]=id; Splay(id,0); } int KTH(int K) { int u=rt; while(1) { if(t[t[u].ch[0]].size+1==K) return u; if(t[t[u].ch[0]].size>=K) u=t[u].ch[0]; else { K-=t[t[u].ch[0]].size+1; u=t[u].ch[1]; } } } void Del(int x) { Splay(x,0); int rk=t[t[x].ch[0]].size; int l=KTH(rk); int r=KTH(rk+2); Splay(l,0); Splay(r,l); t[r].ch[0]=0; t[x].ff=t[x].size=t[x].val=0; pushup(r); pushup(l); } void Print(int x,int &sum) { if(!sum) return ; if(t[x].ch[1]) { Print(t[x].ch[1],sum); } if(!sum) return; if(x>2) { //x=1是正无限的id,x=2是负无限的id sum--; cout<<name[x]<<' '; } if(t[x].ch[0]) Print(t[x].ch[0],sum); } int main() { freopen("rank.in","r",stdin); freopen("rank.out","w",stdout); //srand(time(0)); scanf("%d",&n); insert(2147483647,++tot); insert(-2147483647,++tot); for(int i=1;i<=n;i++) { cin>>x1; if(x1[0]=='+') { x1.erase(0,1); int kl; cin>>kl; if(M[x1]) { int ids=M[x1]; Del(ids); insert(kl,ids); } else { insert(kl,++tot); M[x1]=tot; name[tot]=x1; } } else { if(x1[0]=='?') { x1.erase(0,1); if(x1[0]>='0'&&x1[0]<='9') { int temp=0; for(int j=0;j<x1.size();j++) { temp=temp*10+x1[j]-'0'; } int l=KTH(tot-temp+1); Splay(l,0); int sum=10; Print(t[l].ch[0],sum); cout<<endl; } else { int kkk=M[x1]; Splay(kkk,0); cout<<t[t[kkk].ch[1]].size<<endl; } } } if((i+200)%200==0) { Splay(rand()%tot+1,0); } } return 0; }