洛谷P3369 【模板】普通平衡树(Treap/SBT)
洛谷P3369 【模板】普通平衡树(Treap/SBT)
平衡树,一种其妙的数据结构
题目传送门
题目描述
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
插入x数
删除x数(若有多个相同的数,因只删除一个)
查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)
查询排名为x的数
求x的前驱(前驱定义为小于x,且最大的数)
求x的后继(后继定义为大于x,且最小的数)
输入输出格式
输入格式:
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1≤opt≤6 )
输出格式:
对于操作3,4,5,6每行输出一个数,表示对应答案
输入样例
10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
输出样例
106465
84185
492737
说明
时空限制:1000ms,128M
1.n的数据范围:100000 n≤100000
2.每个数的数据范围: [-10^7——10^7]
注释什么的都写代码里好了
小伙伴们在洛谷上提交不要选c++11
神奇RE和编译失败
如果有dalao看出为什么的话就教教我呗QAQ
#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
int read()
{
int f=1,x=0;
char ss=getchar();
while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
return f*x;
}
int n,ans;
struct node
{
node* ch[2];//左右孩子指针,0为左孩子,1,为右孩子
int v,r;//v为该节点权值;r为优先级
int sum,cnt;//sum表示该节点的子树的节点数,cnt是该节点保存相同权值的个数
node(int v):v(v){ sum=cnt=1; r=rand(); ch[0]=ch[1]=NULL;}//构造函数,用于初始化
int cmp(int x) const{ if(x==v) return -1; return x<v ?0:1; }
//这里的这个成员函数将在下面解释
void update()
{
sum=cnt;
if(ch[0]!=NULL) sum+=ch[0]->sum;
if(ch[1]!=NULL) sum+=ch[1]->sum;
}//更新新函数,在旋转时调用
};
node* rt=NULL;//这个是初始的根
//d=0代表左旋;d=1代表右旋
void rotate(node* &p,int d)//结点记得加引用
{
node* k=p->ch[d^1];
p->ch[d^1]=k->ch[d]; //改变k的子树的位置
k->ch[d]=p;//将k旋转至p上方
p->update();
k->update();
//旋转后要跟新节点信息
p=k;
//将旋转上去的k节点作为当前子树新的根节点
}
void ins(node* &p,int x)//x为带插入权值,结点记得加引用
{
if(p==NULL){ p=new node(x); return; }
//如果结点为NULL ,则找到了带插入结点,进行初始化
if(p->v==x){ p->cnt++; p->sum++; return; }
//如果已有该结点,则cnt++
int d=p->cmp(x);
//这里运用了结构体中的cmp函数,用以确定x该插入左孩子还是右孩子
//若x<该结点权值,cmp返回0,插入左孩子;反之亦然
ins(p->ch[d],x);
//递归插入
if( p->ch[d]->r < p->r ) rotate(p,d^1);
//*划重点*;插入后判断优先级以保证堆的性质
p->update();
//插入后要更新信息
}
void del(node* &p,int x){
if(p==NULL) return;//结点记得加引用
if(x==p->v)//找到待删除结点
{
if(p->cnt>1){ p->sum--; p->cnt--; return;}
//如果该节点记录个数大于一,则直接--,不用删除
else
{
if(p->ch[0]==NULL)
{node *k=p; p=p->ch[1]; delete(k); }
else if(p->ch[1]==NULL)
{node *k=p; p=p->ch[0]; delete(k); }
//如果这个结点只有一棵子树,就以该子树代替该节点
else//如果两棵子树都不为空
{
//先把优先级较高的子树旋转到根
//然后递归再另一颗子树中删除p
int dd=p->ch[0]->r < p->ch[1]->r ?1 :0;
rotate(p,dd); del(p->ch[dd],x);
}
}
}
//递归寻找待删除结点
else if(x < p->v)del(p->ch[0],x);
else del(p->ch[1],x);
if(p!=NULL)p->update();
//删除后一定要更新信息,更新前判断p不为NULL
}
int rank(node* p,int x)//查询函数都不加引用!!!
{
int sum=0;
if(p->ch[0]!=NULL) sum=p->ch[0]->sum;
if(x<p->v) return rank(p->ch[0],x);
//向下寻找待查询结点
if(x==p->v) return sum+1;
//找到待查询结点,则其排名为左子树节点数+1
else return sum+p->cnt+rank(p->ch[1],x);
//待查询权值在右子树内
//则该节点即其左子树必定小于待查询结点
//所以加上该节点左孩子的sum+改点cnt,递归右孩子
}
int kth(node* p,int x)//查询函数都不加引用!!!
{
int sum=0;
if(p->ch[0]!=NULL) sum=p->ch[0]->sum;
if(x<=sum) return kth(p->ch[0],x);
//若待查询排名小于左孩子数,则应继续在左子树递归寻找
else if(x<=sum+p->cnt) return p->v;
//如果排名小于左孩子数加该节点cnt,则该节点为待查询结点
else return kth(p->ch[1],x-sum-p->cnt);
//如果排名还要大,那就要往右子树找
}
void pre(node* p,int x)//查询函数都不加引用!!!
{
if(p==NULL) return;
if( x > p->v ){ ans=p->v; pre(p->ch[1],x);}
//找到小于x的数,但不一定最大,所以找右子树
else pre(p->ch[0],x);
//如果小于等于的话就找左子树啰
}
void nxt(node* p,int x)//查询函数都不加引用!!!
{
//就是和找前驱正好相反啦
if(p==NULL) return ;
if( x < p->v ){ ans=p->v; nxt(p->ch[0],x);}
else nxt(p->ch[1],x);
}
int main()
{
n=read();
for(int i=1;i<=n;i++)
{
int k=read(),x=read();
if(k==1) ins(rt,x);
else if(k==2) del(rt,x);
else if(k==3) cout<<rank(rt,x)<<endl;
else if(k==4) cout<<kth(rt,x)<<endl;
else if(k==5) { pre(rt,x); cout<<ans<<endl; }
else if(k==6) { nxt(rt,x); cout<<ans<<endl; }
}
return 0;
}
给大家看一下蒟蒻的悲惨经历QAQ
一道题; 一百五十行;
两天; 六个小时;
千万个指针; 亿万次调试;
8次提交 ;
终于——
稻花香里说RE,听取 WA声一片;
指针,已使我目不忍视了;旋转,尤使我耳不忍闻;
然而正真的猛士,敢于直面惨淡的AC率,敢于正视淋漓的数据结构;
这是怎样的AC者与OIer!!!
仅使在Treap和SBT的世界中得以暂且偷生;
我不知道平衡树的世界何时才是一个尽头!!
忘却的伸展树快要降临了罢;
我正有学一下Splay的必要了;
沉默呵,沉默呵,不在爆零中灭亡,就AK中爆发;
——《纪念AC君》
洛谷P3369 【模板】普通平衡树(Treap/SBT)的更多相关文章
- luoguP3369[模板]普通平衡树(Treap/SBT) 题解
链接一下题目:luoguP3369[模板]普通平衡树(Treap/SBT) 平衡树解析 #include<iostream> #include<cstdlib> #includ ...
- 洛谷.3369.[模板]普通平衡树(fhq Treap)
题目链接 第一次(2017.12.24): #include<cstdio> #include<cctype> #include<algorithm> //#def ...
- 【洛谷P3369】普通平衡树——Splay学习笔记(一)
二叉搜索树(二叉排序树) 概念:一棵树,若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值: 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值: 它的左.右子树也分别为二叉搜索树 ...
- 洛谷.3369.[模板]普通平衡树(Splay)
题目链接 第一次写(2017.11.7): #include<cstdio> #include<cctype> using namespace std; const int N ...
- 洛谷.3391.[模板]文艺平衡树(Splay)
题目链接 //注意建树 #include<cstdio> #include<algorithm> const int N=1e5+5; //using std::swap; i ...
- 【洛谷P3369】【模板】普通平衡树题解
[洛谷P3369][模板]普通平衡树题解 题目链接 题意: 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3 ...
- 洛谷P3369普通平衡树(Treap)
题目传送门 转载自https://www.cnblogs.com/fengzhiyuan/articles/7994428.html,转载请注明出处 Treap 简介 Treap 是一种二叉查找树.它 ...
- 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)
To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...
- AC日记——【模板】普通平衡树(Treap/SBT) 洛谷 P3369
[模板]普通平衡树(Treap/SBT) 思路: 劳资敲了一个多星期: 劳资终于a了: 劳资一直不a是因为一个小错误: 劳资最后看的模板: 劳资现在很愤怒: 劳资不想谈思路!!! 来,上代码: #in ...
随机推荐
- [拾 得] 一枚迷人的贝壳 SHELL / Linux | shell 脚本初步入门
坚持知识分享,该文章由Alopex编著, 转载请注明源地址: http://www.cnblogs.com/alopex/ 索引: 什么是shell shell的分类 shell脚本的执行方式 ...
- [知了堂学习笔记]_ajax的两种使用方式
一.Ajax概述 1.什么是同步,什么是异步 同步现象:客户端发送请求到服务器端,当服务器返回响应之前,客户端都处于等待 卡死状态 异步现象:客户端发送请求到服务器端,无论服务器是否返回响应,客户端都 ...
- Performance Testing 入门小结
从事软件测试两年多了,一直在做功能测试.2016年计划学习Performance.今天,先把之前听过的同事session以及自己查阅的资料小结一下. 一.什么是性能测试 首先来说一下软件的性能是什么. ...
- TCP三次握手机制中的seq和ack
TCP连接的三次握手:第一次(A--->B),SYN=1,seq=x第二次(B--->A),SYN=1,ACK=1,seq=y,ack=x+1 第三次(A--->B),ACK=1,s ...
- 一道360 crackme的破解
该crackme主要实现都在so中,用ida加载libqihoo.so,出现以下错误 第一个错误说明是节区头部表格的表项大小错误,第二个错误是指节区头部表格的大小或偏移值错误.不管它,点击“Yes”继 ...
- Python初识-day1
1.第一个python程序(在pycharm中运行的,感觉还不错) 注释: 当行注释:#被注释内容 多行注释:''' 被注释内容 ''' 2.变量 (1) 自己理解的定义(仅供参考): 为了存储数据 ...
- linux根据端口号查询来源程序
1.根据端口号查询进程 netstat -tunlp|grep port 2.根据进程查询来源程序 ps aux | grep pid 上图看出所属进程为2281 上图看出占用8083端口的程序为n ...
- <<Senium2自动化测试>>读书笔记一
为进一步加强Python知识扩展和学习,在朋友的推荐下选择了<<Selenium2自动化测试实战>>,作者胡志恒,基于Python语言实现,以实例的方式详细讲解WebDrive ...
- IDEA新建Maven项目
Maven是什么? 当我们在开发一个项目的时候,不可避免地会使用到第三方的类库,而它们又可能依赖着另外的Jar包,又得引入其他Jar包,而且我们很容易就会引漏掉~然后就会报错,有时候报的错会让我们花掉 ...
- Apache Shiro java安全框架
什么是Apache Shiro? Apache Shiro(发音为“shee-roh”,日语“堡垒(Castle)”的意思)是一个强大易用的Java安全框架,提供了认证.授权.加密和会话管理功能,可为 ...