【BZOJ 1056 1862】排名系统

Description

排名系统通常要应付三种请求:上传一条新的得分记录、查询某个玩家的当前排名以及返回某个区段内的排名记录。当某个玩家上传自己最新的得分记录时,他原有的得分记录会被删除。为了减轻服务器负担,在返回某个区段内的排名记录时,最多返回10条记录。

Input

第一行是一个整数n(n>=10)表示请求总数目。接下来n行,每行包含了一个请求。请求的具体格式如下: +Name Score 上传最新得分记录。Name表示玩家名字,由大写英文字母组成,不超过10个字符。Score为最多8位的正整数。 ?Name 查询玩家排名。该玩家的得分记录必定已经在前面上传。 ?Index 返回自第Index名开始的最多10名玩家名字。Index必定合法,即不小于1,也不大于当前有记录的玩家总数。

Output

对于?Name格式的请求,应输出一个整数表示该玩家当前的排名。对于?Index格式的请求,应在一行中依次输出从第Index名开始的最多10名玩家姓名,用一个空格分隔。

Sample Input

20
+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
4

HINT

100%数据满足N<=250000

 

分析:

  HASH表加上平衡树,这里的平衡树需要支持Insert(添加)、Delete(删除)、Rank(查询元素在树中的排名)和Select(找出第k大)。

  需要注意的是,如果两个玩家的得分相同,则比较最后一次更新的时间,而不是加入玩家的时间。

  这里用的是SBT。

 

  1 //
  2 // When I first coded it
  3 // Just God and I could understand it
  4 // But now
  5 // Just God could
  6 // 
  7 
  8 #include <cstdio>
  9 #include <cstring>
 10 
 11 #define HASHMOD 318931
 12 #define MAXN 318931
 13 
 14 int n, sco, len;
 15 int prev[HASHMOD], last[HASHMOD];
 16 int score[HASHMOD], older[HASHMOD], num, old;
 17 int father[MAXN], child[MAXN][2];
 18 int point[MAXN], size[MAXN], cnt, root;
 19 char str[15], hash_value[HASHMOD][15];
 20 
 21 inline int Hash_Insert (int hash, int value)
 22 {
 23     num++;
 24     prev[num] = last[hash];
 25     last[hash] = num;
 26     score[num] = value;
 27     older[num] = ++old;
 28     strcpy (hash_value[num], str);
 29     return num;
 30 }
 31 
 32 inline int Hash_Find (int hash)
 33 {
 34     for (int i = last[hash]; i; i = prev[i])
 35         if (strcmp (hash_value[i], str) == 0)
 36             return i;
 37     return -1;
 38 }
 39 
 40 void Rotate (int& f, int d)
 41 {
 42     int c = child[f][!d];
 43     child[f][!d] = child[c][d];
 44     child[c][d] = f;
 45     size[c] = size[f];
 46     size[f] = size[child[f][0]] + size[child[f][1]] + 1;
 47     f = c;
 48 }
 49 
 50 int NewNode (int p)
 51 {
 52     cnt++;
 53     point[cnt] = p;
 54     size[cnt] = 1;
 55     return cnt;
 56 }
 57 
 58 void MainTain (int& t, int d)
 59 {
 60     if (!t) return;
 61     if (size[child[child[t][d]][d]] > size[child[t][!d]])
 62         Rotate (t, !d);
 63     else if (size[child[child[t][d]][!d]] > size[child[t][!d]])
 64         Rotate (child[t][d], d), Rotate (t, !d);
 65     else return;
 66     MainTain (child[t][0], 0);
 67     MainTain (child[t][1], 1);
 68     MainTain (t, 0);
 69     MainTain (t, 1);
 70 }
 71 
 72 inline bool Cmp (int p, int t)
 73 {
 74     bool ret = score[p] < score[point[t]];
 75     if (score[p] == score[point[t]]) ret = older[p] >= older[point[t]];
 76     return ret;
 77 }
 78 
 79 void Insert (int& t, int p)
 80 {
 81     if (t == 0) t = NewNode (p);
 82     else
 83     {
 84         size[t]++;
 85         int d = Cmp (p, t);
 86         Insert (child[t][d], p);
 87         MainTain (t, d);
 88     }
 89 }
 90 
 91 int Delete (int& t, int p)
 92 {
 93     int Ret;
 94     size[t]--;
 95     int d = Cmp (p, t);
 96     if (p == point[t] || child[t][d] == 0)
 97     {
 98         Ret = point[t];
 99         if (child[t][0] && child[t][1])
100             point[t] = Delete (child[t][0], p);
101         else t = child[t][0] + child[t][1];
102     } else Ret = Delete (child[t][d], p);
103     return Ret;
104 }
105 
106 void DelBoot (int p)
107 {
108     int i = Delete (root, p);
109     if (i != p) Insert (root, i);
110 }
111 
112 inline void modify (int hash)
113 {
114     int id = Hash_Find (hash);
115     if (id < 0) id = Hash_Insert (hash, sco);
116     else DelBoot (id), score[id] = sco, older[id] = ++old;
117     Insert (root, id);
118 }
119 
120 int Rank (int t, int p)
121 {
122     if (t == 0) return -1;
123     if (point[t] == p) return size[child[t][0]] + 1;
124     int d = Cmp (p, t);
125     if (d) return Rank (child[t][1], p) + size[child[t][0]] + 1;
126     return Rank (child[t][0], p);
127 }
128 
129 int Select (int t, int k)
130 {
131     if (t == 0) return -1;
132     if (size[child[t][0]] == k - 1) return point[t];
133     if (size[child[t][0]] > k - 1) return Select (child[t][0], k);
134     return Select (child[t][1], k - size[child[t][0]] - 1);
135 }
136 
137 int main ()
138 {
139     scanf ("%d", &n);
140     for (int i = 0; i < n; i++)
141     {
142         scanf ("%s", str);
143         len = strlen (str);
144         int hash = 0, a = 3785, b = 639;
145         for (int j = 1; j < len; j++)
146         {
147             hash = ((long long) hash * a + (str[j] == '?' ? '+' : str[j])) % HASHMOD;
148             a = a * b % HASHMOD;
149         }
150         if (str[0] == '+')
151         {
152             scanf ("%d", &sco);
153             modify (hash);
154         } else if (str[0] == '?')
155         {
156             if (str[1] > '9')
157             {
158                 str[0] = '+';
159                 printf ("%d\n", Rank (root, Hash_Find (hash)));
160             } else
161             {
162                 sco = 0;
163                 for (int j = 1; j < len; j++)
164                     sco = sco * 10 + str[j] - '0';
165                 for (int j = 0; j < 10 && sco <= size[root]; j++, sco++)
166                 {
167                     if (j > 0) printf (" ");
168                     printf ("%s", hash_value[Select (root, sco)] + 1);
169                 }
170                 printf ("\n");
171             }
172         }
173     }
174 }

 

posted @ 2015-04-27 19:08  Lightning34  阅读(...)  评论(...编辑  收藏