博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【BZOJ 1056 1862】排名系统
阅读量:6773 次
发布时间:2019-06-26

本文共 5812 字,大约阅读时间需要 19 分钟。

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 
9 #include
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 } else161 {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 }

 

转载于:https://www.cnblogs.com/lightning34/p/4461022.html

你可能感兴趣的文章
Delphi 的接口(1) - 前言
查看>>
我和数据库的故事
查看>>
TMainMenu 类[三] - 手动建立菜单(6) : 更换菜单
查看>>
常用 API 函数(6): 菜单函数
查看>>
Azure上的一个kernel panic测试
查看>>
Install CDH5.11 on CentOS 7
查看>>
ZooKeeper学习第二期--ZooKeeper安装配置
查看>>
PXE 启动原理
查看>>
C# 引用lib版本不一样解决方法
查看>>
rxjs 学习(1)-认识 rxjs 和理解 observables
查看>>
17 个 tar 命令实用示例
查看>>
Cocos2dx隐藏iOS7状态栏】通过添加Plist Key隐藏iOS7状态栏
查看>>
大型网站的HTTPS实践之HTTPS对性能的影响
查看>>
smartroute集成聊天通讯集群
查看>>
服务器调试随记
查看>>
java字符串的反转
查看>>
ceph存储 多网卡的7种bond模式原理
查看>>
jquery 鼠标经过效果实例
查看>>
Greenplum和Deepgreen性能简单对比
查看>>
Android 获取手机IMEI方法
查看>>