HihoCoder1325 : 平衡树·Treap(附STL版本)
平衡树·Treap
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
描述
小Ho:小Hi,我发现我们以前讲过的两个数据结构特别相似。
小Hi:你说的是哪两个啊?
小Ho:就是二叉排序树和堆啊,你看这两种数据结构都是构造了一个二叉树,一个节点有一个父亲和两个儿子。 如果用1..n的数组来存储的话,对于二叉树上的一个编号为k的节点,其父亲节点刚好是k/2。并且它的两个儿子节点分别为k*2和k*2+1,计算起来非常方便呢。
小Hi:没错,但是小Hi你知道有一种办法可以把堆和二叉搜索树合并起来,成为一个新的数据结构么?
小Ho:这我倒没想过。不过二叉搜索树满足左子树<根节点<右子树,而堆是满足根节点小于等于(或大于等于)左右儿子。这两种性质是冲突的啊?
小Hi:恩,你说的没错,这两种性质的确是冲突的。
小Ho:那你说的合并是怎么做到的?
小Hi:当然有办法了,其实它是这样的....
输入
第1行:1个正整数n,表示操作数量,10≤n≤100,000
第2..n+1行:每行1个字母c和1个整数k:
若c为'I',表示插入一个数字k到树中,-1,000,000,000≤k≤1,000,000,000
若c为'Q',表示询问树中不超过k的最大数字
输出
若干行:每行1个整数,表示针对询问的回答,保证一定有合法的解
- 样例输入
-
5 I 3 I 2 Q 3 I 5 Q 4
- 样例输出
-
3 3
下午看DXL的资料看到绝望,差点吐了,是真的恶心反胃的那种,也有可能是这几天熬夜的后果。
然后不得不暂时放弃,转向其它姿势点。然后就开始挑战平衡树,如果一拖再拖,也不知道扫时候才有着落。
毕竟,你看看,是不是还有很多树不会的呢,ORZ,orz
由于鄙人不习惯写指针,所以还是保留了一贯是数组写法。
#include<iostream> #include<cstdlib> #include<cstdio> #include<algorithm> using namespace std; const int N=2000010; struct in { int l,r,v,rnd;//v 权值 rnd 堆的优先级 } tree[N]; int ans,cnt,root; void lturn(int &pos) { int tmp=tree[pos].r; tree[pos].r=tree[tmp].l; tree[tmp].l=pos; pos=tmp; } void rturn(int &pos) { int tmp=tree[pos].l; tree[pos].l=tree[tmp].r; tree[tmp].r=pos; pos=tmp; } void insert(int &pos,int x) { if(!pos){ pos=++cnt; tree[cnt].v=x; tree[cnt].rnd=rand(); return ; } if(tree[pos].v==x) return ;//此题无需重复操作 else if(tree[pos].v>x){ insert(tree[pos].l,x); if(tree[tree[pos].l].rnd>tree[pos].rnd) rturn(pos); } else { insert(tree[pos].r,x); if(tree[tree[pos].r].rnd>tree[pos].rnd) lturn(pos); } } void query(int u,int x){ if(u==0) return ; if(tree[u].v<=x){ ans=u; query(tree[u].r,x); } else query(tree[u].l,x); } int main() { int i,x,n,k; char c[2]; scanf("%d",&n); while(n--){ scanf("%s%d",&c,&x); if(c[0]=='I'){ insert(root,x); } else { query(root,x); printf("%d\n",tree[ans].v); } } return 0; }
以及STL版本:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstdlib> #include<set> using namespace std; int main() { int n,x,ans; set<int> s; char c[2]; scanf("%d",&n); while (n--){ scanf("%s%d",&c,&x); if (c[0]=='I') s.insert(x); else{ set<int>::iterator it = s.upper_bound(x); it--; printf("%d\n",*it); } } return 0; }
It is your time to fight!