Treap树模板hdu-4585
Posted lihello
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Treap树模板hdu-4585相关的知识,希望对你有一定的参考价值。
目录
例题:hdu 4585
Treap树
是一种简单的平衡二叉搜索树。
二叉搜索树的每一个节点都有一个键值,除此之外Treap树为每个节点人为添加了一个称之为优先级的权值。对于键值来说,这是一棵二叉搜索树,对于权值来说这是一个堆。
1、Treap树的唯一性
Treap树的重要特性:另每个节点的优先级互不相等,那么整棵树的形态时唯一的,和元素的插入顺序没有关系。
2、Treap树的平衡问题
树的形态依赖于节点的优先级,那么如何配置每个节点的优先级,才能避免二叉树的形态退化成链表?最简单的方法时把每个节点的优先级进行随机赋值,那么生成的Treap树形态也是随机的。这虽然不能保证每次生成的Treap树一定时平衡的,但是期望的插入、删除、查找的复杂度都是O(logn)的。
3、Treap树的数据结构
struct Node
int size; // 以这个点为根的子树的节点的数量
int rank; // 优先级
int key; // 键值
Node *son[2]; //son[0]时左儿子,son[1]是右儿子
bool operator < (const Node &a)const return rank < a.rank;
int cmp(int x)const
if(x == key) return -1;
return x < key? 0 : 1;
void update() //更新size
size = 1;
if(son[0] != NULL) size += son[0] -> size;
if(son[1] != NULL) size += son[1] -> size;
;
4、Treap树的插入
每读入一个新的节点,为它分配一个随机的优先级,插入到树中,在插入时动态调整树的结构,使它仍然是一棵Treap树。
把新节点插入到Treap树的过程有两步
(1)用朴素的插入方法把node按键值的大小插入到合适的子树上去。
(2)给node随机分配一个优先级,如果node的优先级违反了堆的性质,即它的优先级比父节点高,那么让node往上走,替代父节点,最后得到一个新的Treap树。
void insert(Node * &o, int x) //插入
if(o == NULL)
o = new Node();
o -> son[0] = o -> son[1] = NULL;
o -> rank = rand();
o -> key = x;
o -> size = 1;
else
int d = o -> cmp(x);
insert(o -> son[d], x);
o -> update();
if(o < o -> son[d])
rotate(o, d^1);
5、插入过程中维护堆的过程中用到的旋转
void rotate(Node * &o, int d) // d = 0 左旋,d = 1右旋
Node *k = o -> son[d^1]; //d^1 == 1 - d
o -> son[d^1] = k -> son[d];
k -> son[d] = o;
o -> update();
k -> update();
o = k;
6、寻找第k大的数 O(logn)
int kth(Node* o, int k)
if(o == NULL || k <= 0 || k > o -> size)
return -1;
int s = o -> son[1] == NULL? 0: o -> son[1] -> size;
if(k == s + 1) return o -> key;
else if(k <= s) return kth(o -> son[1], k);
else return kth(o -> son[0], k - s - 1);
7、查询某个数的名次 O(logn)
int find(Node* o, int k)
if(o == NULL) return -1;
int d = o -> cmp(k);
if(d == -1)
return o -> son[1] == NULL? 1: o -> son[1] -> size + 1;
else if(d == 1) return find(o -> son[d], k);
else
int tmp = find(o -> son[d], k);
if(tmp == -1) return -1;
else
return o -> son[1] == NULL? tmp + 1: tmp + 1 + o -> son[1] -> size;
8、hdu 4585 AC代码
//#include <bits/stdc++.h>
#include <iostream>
#include <stack>
#include <string>
#include <queue>
#include <stack>
#include <set>
#include <list>
#include <map>
#include <algorithm>
#include <string.h>
#include <time.h>
using namespace std;
int id[5000000 + 5];
struct Node
int size; // 以这个点为根的子树的节点的数量
int rank; // 优先级
int key; // 键值
Node *son[2]; //son[0]时左儿子,son[1]是右儿子
bool operator < (const Node &a)const return rank < a.rank;
int cmp(int x)const
if(x == key) return -1;
return x < key? 0 : 1;
void update() //更新size
size = 1;
if(son[0] != NULL) size += son[0] -> size;
if(son[1] != NULL) size += son[1] -> size;
;
void rotate(Node * &o, int d) // d = 0 左旋,d = 1右旋
Node *k = o -> son[d^1]; //d^1 == 1 - d
o -> son[d^1] = k -> son[d];
k -> son[d] = o;
o -> update();
k -> update();
o = k;
void insert(Node * &o, int x) //插入
if(o == NULL)
o = new Node();
o -> son[0] = o -> son[1] = NULL;
o -> rank = rand();
o -> key = x;
o -> size = 1;
else
int d = o -> cmp(x);
insert(o -> son[d], x);
o -> update();
if(o < o -> son[d])
rotate(o, d^1);
int kth(Node* o, int k)
if(o == NULL || k <= 0 || k > o -> size)
return -1;
int s = o -> son[1] == NULL? 0: o -> son[1] -> size;
if(k == s + 1) return o -> key;
else if(k <= s) return kth(o -> son[1], k);
else return kth(o -> son[0], k - s - 1);
int find(Node* o, int k)
if(o == NULL) return -1;
int d = o -> cmp(k);
if(d == -1)
return o -> son[1] == NULL? 1: o -> son[1] -> size + 1;
else if(d == 1) return find(o -> son[d], k);
else
int tmp = find(o -> son[d], k);
if(tmp == -1) return -1;
else
return o -> son[1] == NULL? tmp + 1: tmp + 1 + o -> son[1] -> size;
int main()
int n;
while(~scanf("%d", &n) && n)
srand(time(NULL));
int k, g;
scanf("%d %d", &k, &g);
Node *root = new Node();
root -> son[0] = root -> son[1] = NULL;
root -> rank = rand();
root -> key = g;
root -> size = 1;
id[g] = k;
printf("%d %d\\n", k, 1);
for(int i = 2; i <= n; i++)
scanf("%d %d", &k, &g);
id[g] = k;
insert(root, g);
int t = find(root, g);
int ans1, ans2, ans;
ans1 = kth(root, t - 1);
ans2 = kth(root, t + 1);
if(ans1 != -1 && ans2 != -1)
ans = ans1 - g >= g - ans2? ans2: ans1;
else if(ans1 == -1) ans = ans2;
else ans = ans1;
printf("%d %d\\n", k, id[ans]);
return 0;
以上是关于Treap树模板hdu-4585的主要内容,如果未能解决你的问题,请参考以下文章