题目大意:维护一种游戏排名系统,为他们的得分排序,若得分一样,则时间早的优先。有的时候要查询一个人是第几名,或者一段名次都是谁。
思路:拿到题一看就知道是暴力Treap乱搞,但是一查不知道看到了谁的文章,说Treap会T,我就战战兢兢的写了Splay,结果T了,拿到数据发现被一个点卡了100s。于是怒写Treap,1.2s怒切。
PS:千万不要相信谣言。。
CODE:
#include <cstdio>
#include <cctype>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 300010
#define MO 299997
#define BASE 133
#define SIZE(a) ((a) == NULL ? 0:(a)->size)
using namespace std;
unsigned long long GetHash(char *s);
struct HashSet{
int head[MAX],total;
int next[MAX];
unsigned long long hash[MAX];
char src[MAX][12];
int Insert(char *s) {
unsigned long long _hash = GetHash(s);
int x = _hash % MO;
for(int i = head[x]; i; i = next[i])
if(hash[i] == _hash)
return i;
next[++total] = head[x];
hash[total] = _hash;
head[x] = total;
strcpy(src[total],s);
return total;
}
}map;
struct Treap{
int random,val,T,name;
int size;
Treap *son[2];
Treap(int _,int __,int ___):val(_),T(__),name(___) {
size = 1;
son[0] = son[1] = NULL;
random = rand();
}
int Compare(int _val,int _T) {
if(_val == val) {
if(T == _T) return -1;
return T < _T;
}
return val > _val;
}
void Maintain() {
size = 1;
if(son[0] != NULL) size += son[0]->size;
if(son[1] != NULL) size += son[1]->size;
}
}*root = NULL;
int cnt;
int score;
char c,name[12];
int now[MAX],_time[MAX];
unsigned long long GetHash(char *s)
{
unsigned long long re = 0;
while(*s != '\0')
re = re * BASE + *s++;
return re;
}
inline void Rotate(Treap *&a,bool dir)
{
Treap *k = a->son[!dir];
a->son[!dir] = k->son[dir];
k->son[dir] = a;
a->Maintain(),k->Maintain();
a = k;
}
void Insert(Treap *&a,int score,int t,int name)
{
if(a == NULL) {
a = new Treap(score,t,name);
return ;
}
int dir = a->Compare(score,t);
Insert(a->son[dir],score,t,name);
if(a->son[dir]->random > a->random)
Rotate(a,!dir);
a->Maintain();
}
void Delete(Treap *&a,int score,int t)
{
int dir = a->Compare(score,t);
if(dir != -1)
Delete(a->son[dir],score,t);
else {
if(a->son[0] == NULL) a = a->son[1];
else if(a->son[1] == NULL) a = a->son[0];
else {
int _ = (a->son[0]->random > a->son[1]->random);
Rotate(a,_);
Delete(a->son[_],score,t);
}
}
if(a != NULL) a->Maintain();
}
int Rank(Treap *a,int k)
{
if(k <= SIZE(a->son[0])) return Rank(a->son[0],k);
k -= SIZE(a->son[0]);
if(k == 1) return a->name;
return Rank(a->son[1],k - 1);
}
int Find(Treap *a,int score,int t)
{
int dir = a->Compare(score,t);
if(dir == 0) return Find(a->son[0],score,t);
if(dir == -1) return SIZE(a->son[0]) + 1;
return SIZE(a->son[0]) + 1 + Find(a->son[1],score,t);
}
int main()
{
cin >> cnt;
for(int i = 1; i <= cnt; ++i) {
while(c = getchar(),c == ' ' || c == '\n' || c == '\r' || c == '\t');
if(c == '+') {
scanf("%s%d",name,&score);
int x = map.Insert(name);
if(now[x]) Delete(root,now[x],_time[x]);
now[x] = score,_time[x] = i;
Insert(root,now[x],_time[x],x);
}
else {
c = getchar();
ungetc(c,stdin);
if(isdigit(c)) {
int st,ed;
scanf("%d",&st);
ed = min(st + 9,map.total);
for(int i = st; i <= ed; ++i) {
if(i != st) putchar(' ');
printf("%s",map.src[Rank(root,i)]);
}
puts("");
}
else {
scanf("%s",name);
int x = map.Insert(name);
printf("%d\n",Find(root,now[x],_time[x]));
}
}
}
return 0;
}