Treap小结

2024-06-16 01:38
文章标签 小结 treap

本文主要是介绍Treap小结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Treap(Tree+Heap)---是一种通过 rand() 来随机生成数字作为修正值来调整的平衡树。

基本操作:

1.旋转。

2.插入(合并重复的),删除(懒惰删除)。

3.查最值,求第k小,求排名。

4.中序遍历就是从小到大的。

5.维护附加关键字.

1.求第k小:

POJ1442

//12321199		1442	Accepted	976K	204MS	C++	2080B	2013-11-22 20:33:35静态
//12321216		1442	Accepted	1804K	329MS	C++	2125B	2013-11-22 20:39:40动态
#include <iostream>
#include<cstdio>
#include<ctime>
#include<cstring>
#include<cstdlib>
using namespace std;
#define MAX 30005
int a[MAX];
int u[MAX];
int tot;
class Node
{
public:int vol,fix;int size;Node *left;Node *right;int lsize(){return left?left->size:0;}int rsize(){return right?right->size:0;}
}*root;//space[MAX]
void left_rotate(Node *&a)
{Node *b=a->right;a->right=b->left;b->left=a;a=b;b=a->left;b->size=b->lsize()+b->rsize()+1;a->size=a->lsize()+a->rsize()+1;
}
void right_rotate(Node *&a)
{Node *b=a->left;a->left=b->right;b->right=a;a=b;b=a->right;b->size=b->lsize()+b->rsize()+1;a->size=a->lsize()+a->rsize()+1;
}
void insert(Node*&p,int vol)
{if(!p){p=new Node();//p=&space[tot++];  //静态p->fix=rand();p->vol=vol;p->size=1;}else if(vol<=p->vol){insert(p->left,vol);p->size++;if(p->left->fix < p->fix)right_rotate(p);}else{insert(p->right,vol);p->size++;if(p->right->fix < p->fix)left_rotate(p);}
}
int get_kth(Node *&p,int k)
{int key=p->lsize()+1;if(k < key)return get_kth(p->left,k);else if(k > key)return get_kth(p->right,k-key);elsereturn p->vol;
}
void init()
{root=NULL;//memset(space,0,sizeof(space));静态//tot=1;
}
int main()
{srand(time(0));int n,m;while(~scanf("%d%d",&m,&n)){for(int i=1;i<=m;i++) scanf("%d",&a[i]);for(int i=1;i<=n;i++) scanf("%d",&u[i]);int j=1;init();for(int i=1;i<=m;i++){insert(root,a[i]);while(j<=n&&i==u[j]){printf("%d\n",get_kth(root,j));j++;}if(j>n) break;}}return 0;
}

2.动态求最值

//12321728		3481	Accepted	212K	282MS	C++	1857B	2013-11-22 22:26:19动态
#include <iostream>
#include<cstdlib>
#include<ctime>
#include<cstdio>
#include<cstring>
using namespace std;
//#define MAX 10000005
class Node
{
public:int vol,fix,cus;Node* left;Node* right;
}*root;//,space[MAX]  
int tot=1;
void r_rotate(Node*&a)
{Node*b=a->left;a->left=b->right;b->right=a;a=b;b=a->right;
}
void l_rotate(Node*&a)
{Node*b=a->right;a->right=b->left;b->left=a;a=b;b=a->left;
}
void insert(Node*&p,int cus,int vol)
{if(!p){p=new Node();//p=&space[tot++];p->fix=rand();p->vol=vol;p->cus=cus;}else if(p->vol >= vol){insert(p->left,cus,vol);if(p->left->fix < p->fix)r_rotate(p);}else{insert(p->right,cus,vol);if(p->right->fix < p->fix)l_rotate(p);}
}
int Min(Node*&p)
{if(!p)return 0;if(!p->left){Node*t=p;int ans=p->cus;p=p->right;delete t;return ans;}else return Min(p->left);
}
int Max(Node*&p)
{if(!p)return 0;if(!p->right){Node*t=p;int ans=p->cus;p=p->left;delete t;return ans;}else return Max(p->right);
}
int main()
{srand(time(0));int a;while(~scanf("%d",&a)&&a){if(a==1){int b,c;scanf("%d%d",&b,&c);insert(root,b,c);}else if(a==3){printf("%d\n",Min(root));}else{printf("%d\n",Max(root));}}return 0;
}

3.区间第k小:

//12329808		2761	Accepted	3500K	1844MS	C++	3889B	2013-11-25 21:28:45静态
//12329836		2761	Accepted	3900K	3922MS	C++	3962B	2013-11-25 21:34:10动态
#include <iostream>
#include<cstdio>
#include<ctime>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAX 2000005
int dog[MAX];
int ans[MAX];
class Interval
{
public:int s,e,k;int id;bool operator<(const Interval a) const{return s<a.s;}
}qu[MAX];
class Node
{
public:int vol,fix,size;Node*left;Node*right;int lsize(){return left?left->size:0;}int rsize(){return right?right->size:0;}
}*root,space[MAX];
int tot;
void r_rotate(Node*&a)
{Node*b=a->left;a->left=b->right;b->right=a;a=b;b=a->right;b->size=b->lsize()+b->rsize()+1;/**RE在这里,不要把求size顺序搞反了*/a->size=a->lsize()+a->rsize()+1;}
void l_rotate(Node*&a)
{Node*b=a->right;a->right=b->left;b->left=a;a=b;b=a->left;b->size=b->lsize()+b->rsize()+1;a->size=a->lsize()+a->rsize()+1;}
void insert(Node*&p,int vol)
{if(!p){p=&space[tot++];//p=new Node();p->left=NULL;p->right=NULL;p->fix=rand();p->vol=vol;p->size=1;}else if(p->vol > vol){p->size++;insert(p->left,vol);if(p->left->fix < p->fix)r_rotate(p);}else{p->size++;insert(p->right,vol);if(p->right->fix < p->fix)l_rotate(p);}
}
void del(Node*&p,int key)
{if(!p) return ;p->size--;  /**注意size的减减**/if(key==p->vol){if(!p->left || !p->right){//Node *t=p;if(!p->left)p=p->right;elsep=p->left;//delete t;}else{if(p->right->fix < p->left->fix){l_rotate(p);p->size--;/**注意size的减减**/del(p->left,key);}else{r_rotate(p);p->size--;/**注意size的减减**/del(p->right,key);}}}else if(key < p->vol)del(p->left,key);elsedel(p->right,key);
}
int find_kth(Node*&p,int k)
{int sum=p->lsize()+1;if(k < sum){return find_kth(p->left,k);}else if(k>sum){return find_kth(p->right,k-sum);}else{return p->vol;}
}
int solve(Interval t1,Interval t2)
{for(int i=t1.s;i<=min(t2.s-1,t1.e);i++)del(root,dog[i]);if(t1.e > t2.e){for(int i=t2.e+1;i<=t1.e;i++)del(root,dog[i]);}for(int i=max(t1.e+1,t2.s);i<=t2.e;i++)insert(root,dog[i]);return find_kth(root,t2.k);
}
int main()
{srand(time(0));//int T;//scanf("%d",&T);int n,m;while(~scanf("%d%d",&n,&m)){root=NULL;tot=1;memset(space,NULL,sizeof(space));for(int i=1;i<=n;i++)scanf("%d",&dog[i]);for(int i=1;i<=m;i++){scanf("%d%d%d",&qu[i].s,&qu[i].e,&qu[i].k);if(qu[i].s > qu[i].e) swap(qu[i].s,qu[i].e);qu[i].id=i;}sort(qu+1,qu+1+m);for(int i=qu[1].s;i<=qu[1].e;i++)insert(root,dog[i]);ans[qu[1].id]=find_kth(root,qu[1].k);for(int i=2;i<=m;i++){ans[qu[i].id]=solve(qu[i-1],qu[i]);}for(int i=1;i<=m;i++)printf("%d\n",ans[i]);}return 0;
}




这篇关于Treap小结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1065160

相关文章

判断PyTorch是GPU版还是CPU版的方法小结

《判断PyTorch是GPU版还是CPU版的方法小结》PyTorch作为当前最流行的深度学习框架之一,支持在CPU和GPU(NVIDIACUDA)上运行,所以对于深度学习开发者来说,正确识别PyTor... 目录前言为什么需要区分GPU和CPU版本?性能差异硬件要求如何检查PyTorch版本?方法1:使用命

Redis 热 key 和大 key 问题小结

《Redis热key和大key问题小结》:本文主要介绍Redis热key和大key问题小结,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录一、什么是 Redis 热 key?热 key(Hot Key)定义: 热 key 常见表现:热 key 的风险:二、

Spring Boot读取配置文件的五种方式小结

《SpringBoot读取配置文件的五种方式小结》SpringBoot提供了灵活多样的方式来读取配置文件,这篇文章为大家介绍了5种常见的读取方式,文中的示例代码简洁易懂,大家可以根据自己的需要进... 目录1. 配置文件位置与加载顺序2. 读取配置文件的方式汇总方式一:使用 @Value 注解读取配置方式二

Python中的getopt模块用法小结

《Python中的getopt模块用法小结》getopt.getopt()函数是Python中用于解析命令行参数的标准库函数,该函数可以从命令行中提取选项和参数,并对它们进行处理,本文详细介绍了Pyt... 目录getopt模块介绍getopt.getopt函数的介绍getopt模块的常用用法getopt模

C 语言中enum枚举的定义和使用小结

《C语言中enum枚举的定义和使用小结》在C语言里,enum(枚举)是一种用户自定义的数据类型,它能够让你创建一组具名的整数常量,下面我会从定义、使用、特性等方面详细介绍enum,感兴趣的朋友一起看... 目录1、引言2、基本定义3、定义枚举变量4、自定义枚举常量的值5、枚举与switch语句结合使用6、枚

Java中的Lambda表达式及其应用小结

《Java中的Lambda表达式及其应用小结》Java中的Lambda表达式是一项极具创新性的特性,它使得Java代码更加简洁和高效,尤其是在集合操作和并行处理方面,:本文主要介绍Java中的La... 目录前言1. 什么是Lambda表达式?2. Lambda表达式的基本语法例子1:最简单的Lambda表

Java中Scanner的用法示例小结

《Java中Scanner的用法示例小结》有时候我们在编写代码的时候可能会使用输入和输出,那Java也有自己的输入和输出,今天我们来探究一下,对JavaScanner用法相关知识感兴趣的朋友一起看看吧... 目录前言一 输出二 输入Scanner的使用多组输入三 综合练习:猜数字游戏猜数字前言有时候我们在

SQL BETWEEN 的常见用法小结

《SQLBETWEEN的常见用法小结》BETWEEN操作符是SQL中非常有用的工具,它允许你快速选取某个范围内的值,本文给大家介绍SQLBETWEEN的常见用法,感兴趣的朋友一起看看吧... 在SQL中,BETWEEN是一个操作符,用于选取介于两个值之间的数据。它包含这两个边界值。BETWEEN操作符常用

go 指针接收者和值接收者的区别小结

《go指针接收者和值接收者的区别小结》在Go语言中,值接收者和指针接收者是方法定义中的两种接收者类型,本文主要介绍了go指针接收者和值接收者的区别小结,文中通过示例代码介绍的非常详细,需要的朋友们下... 目录go 指针接收者和值接收者的区别易错点辨析go 指针接收者和值接收者的区别指针接收者和值接收者的

python uv包管理小结

《pythonuv包管理小结》uv是一个高性能的Python包管理工具,它不仅能够高效地处理包管理和依赖解析,还提供了对Python版本管理的支持,本文主要介绍了pythonuv包管理小结,具有一... 目录安装 uv使用 uv 管理 python 版本安装指定版本的 Python查看已安装的 Python