【模板】Treap (模板题:洛谷P3369普通平衡树)
来源:互联网 发布:什么淘宝炒作 编辑:程序博客网 时间:2024/05/16 01:04
题目描述
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
插入x数
删除x数(若有多个相同的数,因只删除一个)
查询x数的排名(若有多个相同的数,因输出最小的排名)
查询排名为x的数
求x的前驱(前驱定义为小于x,且最大的数)
- 求x的后继(后继定义为大于x,且最小的数)
输入输出格式
输入格式:第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)
输出格式:对于操作3,4,5,6每行输出一个数,表示对应答案
输入输出样例
输入样例#1:
101 1064654 11 3177211 4609291 6449851 841851 898516 819681 4927375 493598
输出样例#1:
10646584185492737
说明
时空限制:1000ms,128M
1.n的数据范围:n<=100000
2.每个数的数据范围:[-1e7,1e7]
#include<iostream>#include<cstdio>#include<cstdlib>using namespace std;struct TREAP{int l,r,val,sz,recy,rd;//sz表示树的节点数,recy记录自己被重复了几次//rd表示该节点的优先级 }t[1000000];int m,size,root,ans;void update(int k){t[k].sz=t[t[k].l].sz+t[t[k].r].sz+t[k].recy;//更新维护 }void left_rotate(int &k){int y=t[k].r;t[k].r=t[y].l;t[y].l=k;t[y].sz=t[k].sz;update(k);k=y;//左旋,至于这里的k=y,由于下面的递归调用,//它会一直迭代,所以无需担心会有什么错误 }void right_rotate(int &k){int y=t[k].l;t[k].l=t[y].r;t[y].r=k;t[y].sz=t[k].sz;update(k);k=y;//右旋 }//以下函数的调用中(int k)表示在根为k的子树中void insert(int &k,int x){//插入操作 if (k==0){//无节点时特判, //或是递归的边界,即插入叶节点 ++size;k=size;t[k].sz=t[k].recy=1;t[k].val=x;t[k].rd=rand();return ; //rand()生成随机的优先级,保证了期望复杂度 }++t[k].sz;//每次向下找同时增加该节点1个节点数if (t[k].val==x) ++t[k].recy; //如果是相同数字,只需++recy即可 else if (x>t[k].val){insert(t[k].r,x);if (t[t[k].r].rd<t[k].rd) left_rotate(k); //插入后如果违反堆性质,就进行上浮 }else{insert(t[k].l,x);if (t[t[k].l].rd<t[k].rd) right_rotate(k);}}void del(int &k,int x){if (k==0) return ;//无节点就跳出 if (t[k].val==x){if (t[k].recy>1){--t[k].recy;--t[k].sz;return ;//如果重复了,只需--recy即可 }if (t[k].l*t[k].r==0) k=t[k].l+t[k].r; //如果左右儿子有为空的情况//或将其变为其儿子节点,或将其删除 else if (t[t[k].l].rd<t[t[k].r].rd) right_rotate(k),del(k,x); //如果其左右儿子都有,选择优先级较大的,//保持以后的堆性质,同时将k节点下沉 else left_rotate(k),del(k,x);}else if (x>t[k].val)--t[k].sz,del(t[k].r,x);//如果关键值不同,继续向下找 else --t[k].sz,del(t[k].l,x);}int atrank(int k,int x){//寻找值为x的数的排名 if (k==0) return 0;if (t[k].val==x) return t[t[k].l].sz+1;//如果找的关键字,根据BST的性质,//则其排名为左子树的大小+1 else if (x>t[k].val)return t[t[k].l].sz+t[k].recy+atrank(t[k].r,x);//加上前面所有比它小的数,在右子树中找 else return atrank(t[k].l,x); //如果在左子树中找的话就不用加了 }int rerank(int k,int x){//寻找排名为x的数值 if (k==0) return 0;if (x<=t[t[k].l].sz) return rerank(t[k].l,x);//如果x小于了左子树的大小,那解一定在左子树中 else if (x>t[t[k].l].sz+t[k].recy)return rerank(t[k].r,x-t[k].recy-t[t[k].l].sz);//如果x大于的左子树的大小+k的重复次数,//那就在右子树中找 else return t[k].val; //否则就是找到解了(包含了重复数字中) }void pred(int k,int x){//找前缀 if (k==0) return ;if (t[k].val<x){ans=k;pred(t[k].r,x);//找到了更优的解,就替换之//而且在其右子树中不可能再有更优的了//故向其左子树中找}else pred(t[k].l,x);//否则就往右子树中找 }void succ(int k,int x){//找后缀 if (k==0) return ;if (t[k].val>x){ans=k;succ(t[k].l,x);}else succ(t[k].r,x);}int main(){int f,x;scanf("%d",&m);for (int i=1;i<=m;++i){scanf("%d%d",&f,&x);ans=0;if (f==1) insert(root,x);if (f==2) del(root,x);if (f==3) printf("%d\n",atrank(root,x));if (f==4) printf("%d\n",rerank(root,x));if (f==5) {pred(root,x);printf("%d\n",t[ans].val);}if (f==6) {succ(root,x);printf("%d\n",t[ans].val);}}return 0;}
阅读全文
2 0
- 【模板】Treap (模板题:洛谷P3369普通平衡树)
- 洛谷 P3369 【模板】普通平衡树(Treap/SBT)
- 洛谷 P3369 【模板】普通平衡树(Treap/SBT)
- 【模板】【Treap/SBT】【树堆】普通平衡树【洛谷P3369】
- P3369 【模板】普通平衡树(Treap/SBT)
- P3369 【模板】普通平衡树(Treap/SBT)
- 3224: Tyvj 1728 普通平衡树 P3369 【模板】普通平衡树(Treap/SBT)Treap
- 洛谷P3369 普通平衡树(Treap/Splay)
- 【模板】普通平衡树 Treap
- 【treap模板】【TyvJ 1728】【普通平衡树】
- BZOJ 3224 普通平衡树 裸treap模板题
- BZOJ 3224 洛谷 3369 【模板】普通平衡树(Treap/SBT)
- [平衡树模板]Treap
- [模板]平衡树treap
- BZOJ3224:普通平衡树(含SBT、Treap、Splay模板)
- 【模板】【bzoj3224】Tyvj 1728 普通平衡树 Treap
- Treap模板 BZOJ 3224: Tyvj 1728 普通平衡树
- Treap 全操作模板 bzoj 3224 普通平衡树
- 制作Unity插件之-创建一个Window窗口
- spring ioc 3
- Datatables Server-side processing
- python基础------正则表达式
- SSH客户端开发开源组件Ganymed SSH-2 for Java初体验
- 【模板】Treap (模板题:洛谷P3369普通平衡树)
- less 运算、函数
- spring aop 1
- Sql查询--sql语句的执行顺序
- jvm内存结构
- 安卓中图片色彩的存储方式及对ARGB_8888、ARGB_4444、RGB_565、ALPHA_8的理解
- android:taskAffinity属性的简单测试
- 用Excel创建条形码
- opencv 分水岭算法watershed