您的位置:首页 > 其它

HDU 4585 Shaolin(Treap)

2017-07-21 11:43 375 查看
题目链接:点击打开链接

题意:

少林寺的每个和尚均有编号和战斗等级,新来的小和尚均要和老和尚比试,从老和尚中选和自己的战斗等级相差最少的比,如果有两个,选比自己战斗等级小的和尚。每个和尚的编号和战斗等级均唯一。

其实这是个水题,直接用map即可,但为了练习Treap,采用Treap方法。

可以想到采用的数据结构要能动态的维护一个有序序列(战斗等级,由于战斗等级和编号为一对一映射,直接维护战斗等级即可),一边插入新值,一边维护有序性,不能采用数组和链表,这两者都是O(N)级别,所以可以采用O(logN)级别的二叉搜索树,而且为了效率,采用二叉平衡搜索树,二叉平衡搜索树中,Treap代码相对于Splay树和AVL树最简单,首选Treap。

// HDU 4585 Shaolin.cpp 运行/限制:452ms/1000ms
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
using namespace std;
#define MAXN 100005
#define MAX 0X3f3f3f3f
class Treap {
public:
int root, treapCnt;
int child[MAXN][2], key[MAXN],priority[MAXN],size[MAXN];
Treap() {
root = 0;
treapCnt = 0;
priority[0] = MAX;
size[0] = 0;
}
void update(int x) {
size[x] = size[child[x][0]] + size[child[x][1]] + 1;
}
void rotate(int &x, int index) {
int y = child[x][index];
child[x][index] = child[y][1 - index];
child[y][1 - index] = x;
update(x);
update(y);
x = y;
}
int find(int x,int value) {//利用size数组查找大小顺序 是此题重点
if (key[x] == value) {
return size[child[x][0]] + 1;
}
else if (value < key[x]) {
return find(child[x][0], value);
}
else {
return size[child[x][0]] + 1 + find(child[x][1], value);
}
}
void insert(int &x, int value) {
if (x == 0) {
x = ++treapCnt;
key[x] = value;
child[x][0] = child[x][1] = 0;
size[x] = 1;
priority[x] = rand();
return;
}
if (value < key[x]) {
insert(child[x][0],value);
if (priority[child[x][0]] < priority[x]) {
rotate(x, 0);
}
}
else {
insert(child[x][1], value);
if (priority[child[x][1]] < priority[x]) {
rotate(x, 1);
}
}
update(x);
}
int findKth(int x, int k) {
if (size[child[x][0]] >= k) {
return findKth(child[x][0], k);
}
else if (size[child[x][0]] == k - 1) {
return key[x];
}
else {
return findKth(child[x][1], k - size[child[x][0]] - 1);
}
}
};
int main(){
int n,id,value;
map<int,int> m;
while (scanf("%d", &n) != EOF && n) {
Treap *t = new Treap();
m.clear();
t->insert(t->root, 1000000000);
m[1000000000] = 1;
for (int i = 0; i < n; i++) {
scanf("%d%d", &id, &value);
m[value] = id;
t->insert(t->root, value);
int rank = t->find(t->root, value);//查找大小顺序
int v1 = rank == 1?-MAX:t->findKth(t->root,rank - 1);
int v2 = rank == t->treapCnt?MAX:t->findKth(t->root,rank + 1);
v1 = value - v1 <= v2 - value ? v1 : v2;
printf("%d %d\n", id, m[v1]);
}
delete t;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: