Description
GameZ为他们最新推出的游戏开通了一个网站。世界各地的玩家都可以将自己的游戏得分上传到网站上。这样就可以看到自己在世界上的排名。得分越高,排名就越靠前。当两个玩家的名次相同时,先上传记录者优先。由于新游戏的火爆,网站服务器已经难堪重负。为此GameZ雇用了你来帮他们重新开发一套新的核心。排名系统通常要应付三种请求:上传一条新的得分记录、查询某个玩家的当前排名以及返回某个区段内的排名记录。当某个玩家上传自己最新的得分记录时,他原有的得分记录会被删除。为了减轻服务器负担,在返回某个区段内的排名记录时,最多返回10条记录。
Input
第一行是一个整数n(n>=10)表示请求总数目。接下来n行每行包含了一个请求。请求的具体格式如下: +Name Score 上传最新得分记录。Name表示玩家名字,由大写英文字母组成,不超过10个字符。Score为最多8位的正整数。 ?Name 查询玩家排名。该玩家的得分记录必定已经在前面上传。 ?Index 返回自第Index名开始的最多10名玩家名字。Index必定合法,即不小于1,也不大于当前有记录的玩家总数。输入文件总大小不超过2M。 NOTE:用C++的fstream读大规模数据的效率较低
Output
对于每条查询请求,输出相应结果。对于?Name格式的请求,应输出一个整数表示该玩家当前的排名。对于?Index格式的请求,应在一行中依次输出从第Index名开始的最多10名玩家姓名,用一个空格分隔。
Sample Input
+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的排名
Sample 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
cnmd辣鸡题目范围都不给清楚?
调了一上午心态爆炸
其实只要把树稍微修改一下,原本是左子树是小于的数
这个题弄成左子树是小于等于的数
唯一把find函数和其他函数包含Cnt数组部分稍作修改即可。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<map> 5 #define MAXN (1000000+10) 6 #define LL long long 7 using namespace std; 8 LL Father[MAXN]; 9 LL Son[MAXN][2]; 10 LL Key[MAXN]; 11 LL Size[MAXN]; 12 LL Root,sz; 13 map<string,LL>Num; 14 map<LL,string>Name; 15 LL n; 16 char c[101]; 17 18 inline void Clear(LL x) 19 { 20 Father[x]=Son[x][0]=Son[x][1]=Key[x]=Size[x]=0; 21 } 22 23 inline LL Get(LL x) 24 { 25 return Son[Father[x]][1]==x; 26 } 27 28 inline void Update(LL x) 29 { 30 Size[x]=1+Size[Son[x][0]]+Size[Son[x][1]]; 31 } 32 33 inline void Rotate(LL x) 34 { 35 LL wh=Get(x); 36 LL fa=Father[x],fafa=Father[fa]; 37 Son[fa][wh]=Son[x][wh^1];//fa 38 Father[fa]=x; 39 if (Son[fa][wh]) Father[Son[fa][wh]]=fa; 40 Son[x][wh^1]=fa;//x 41 Father[x]=fafa; 42 if (fafa) Son[fafa][Son[fafa][1]==fa]=x;//fafa 43 Update(fa); 44 Update(x); 45 } 46 47 inline void Splay(LL x) 48 { 49 for (LL fa; fa=Father[x]; Rotate(x)) 50 if (Father[fa]) 51 Rotate(Get(fa)==Get(x)?fa:x); 52 Root=x; 53 } 54 55 inline LL Pre() 56 { 57 LL now=Son[Root][0]; 58 while (Son[now][1]) 59 now=Son[now][1]; 60 return now; 61 } 62 63 inline void Insert(LL x) 64 { 65 if (!Root) 66 { 67 Key[++sz]=x; 68 Root=sz; 69 Size[sz]=1; 70 return; 71 } 72 LL fa=0,now=Root; 73 while (1) 74 { 75 fa=now; 76 now=Son[now][x>Key[now]]; 77 if (!now) 78 { 79 Key[++sz]=x; 80 Father[sz]=fa; 81 Size[sz]=1; 82 Son[fa][x>Key[fa]]=sz; 83 Update(fa); 84 Splay(sz); 85 break; 86 } 87 } 88 } 89 inline LL Find(LL x) 90 { 91 LL Ans=0,now=Root; 92 while (1) 93 if (Key[x]<Key[now] || Key[x]==Key[now] && x>now) 94 //这里稍作修改,因为当数相等时肯定后面加入的更小,所以节点的编号可以看作第二关键字 95 now=Son[now][0]; 96 else 97 { 98 Ans+=Size[Son[now][0]]; 99 if (x==now) 100 { 101 Splay(now); 102 return Ans+1; 103 } 104 Ans++; 105 now=Son[now][1]; 106 } 107 } 108 109 inline LL Findx(LL x) 110 { 111 LL now=Root; 112 while (1) 113 if (x<=Size[Son[now][0]]) 114 now=Son[now][0]; 115 else 116 { 117 x-=Size[Son[now][0]]; 118 if (x==1) 119 { 120 Splay(now); 121 return now; 122 } 123 x--; 124 now=Son[now][1]; 125 } 126 } 127 128 inline void Delete(LL x) 129 { 130 Splay(x); 131 if (!Son[Root][0] && !Son[Root][1]) 132 { 133 Clear(Root); 134 Root=0; 135 return; 136 } 137 if (!Son[x][0]) 138 { 139 Root=Son[Root][1]; 140 Clear(Father[Root]); 141 Father[Root]=0; 142 return; 143 } 144 if (!Son[x][1]) 145 { 146 Root=Son[Root][0]; 147 Clear(Father[Root]); 148 Father[Root]=0; 149 return; 150 } 151 LL Oldroot=Root; 152 LL pre=Pre(); 153 Splay(pre); 154 Son[Root][1]=Son[Oldroot][1]; 155 Father[Son[Root][1]]=Root; 156 Clear(Oldroot); 157 Update(Root); 158 } 159 160 void Work1()//+ 161 { 162 LL s; 163 string st=""; 164 for (LL i=1; i<=strlen(c)-1; ++i) 165 st+=c[i]; 166 if (Num[st]) Delete(Num[st]); 167 scanf("%lld",&s); 168 Insert(s); 169 Name[Root]=st; 170 Num[st]=Root; 171 } 172 173 void Work2() 174 { 175 LL s=0; 176 string st=""; 177 for (LL i=1; i<=strlen(c)-1; ++i) 178 { 179 if (c[i]>='A' && c[i]<='Z') 180 st+=c[i]; 181 if (c[i]>='0' && c[i]<='9') 182 s=s*10+c[i]-48; 183 } 184 if (st!="") 185 printf("%lld",Size[Root]-Find(Num[st])+1); 186 if (s) 187 { 188 LL i=Size[Root]-s+1,sum=1; 189 cout<<Name[Findx(i)]; 190 i--; 191 while (i>=1) 192 { 193 cout<<' '<<Name[Findx(i)]; 194 i--; 195 sum++; 196 if (sum==10) break; 197 } 198 199 } 200 printf(" "); 201 } 202 203 int main() 204 { 205 scanf("%lld",&n); 206 for (LL i=1; i<=n; ++i) 207 { 208 scanf("%s",&c); 209 if (c[0]=='+') 210 Work1(); 211 else 212 Work2(); 213 } 214 }