bzoj3196 二逼平衡树 树套树(线段树套Treap)
Tyvj 1730 二逼平衡树
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 4697 Solved: 1798
[Submit][Status][Discuss]
Description
您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:
1.查询k在区间内的排名
2.查询区间内排名为k的值
3.修改某一位值上的数值
4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)
5.查询k在区间内的后继(后继定义为大于x,且最小的数)
Input
第一行两个数 n,m 表示长度为n的有序序列和m个操作
第二行有n个数,表示有序序列
下面有m行,opt表示操作标号
若opt=1 则为操作1,之后有三个数l,r,k 表示查询k在区间[l,r]的排名
若opt=2 则为操作2,之后有三个数l,r,k 表示查询区间[l,r]内排名为k的数
若opt=3 则为操作3,之后有两个数pos,k 表示将pos位置的数修改为k
若opt=4 则为操作4,之后有三个数l,r,k 表示查询区间[l,r]内k的前驱
若opt=5 则为操作5,之后有三个数l,r,k 表示查询区间[l,r]内k的后继
Output
对于操作1,2,4,5各输出一行,表示查询结果
Sample Input
4 2 2 1 9 4 0 1 1
2 1 4 3
3 4 10
2 1 4 3
1 2 5 9
4 3 9 5
5 2 8 5
Sample Output
4
3
4
9
HINT
1.n和m的数据范围:n,m<=50000
2.序列中每个数的数据范围:[0,1e8]
Source
题解:
这道题目的第二个操作没什么办法,唉,记得当时有log n 的算法的,现在只有log^2n的算法,o( ̄ヘ ̄o#)
线段树套平衡树吧,这里选的是Treap
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<cstdio> #define N 200007
#define M 4000007
#define inf 2000000007
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch>''||ch<''){if (ch=='-') f=-;ch=getchar();}
while(ch<=''&&ch>=''){x=(x<<)+(x<<)+ch-'';ch=getchar();}
return x*f;
} int n,m,ans,sz;
int ls[M],rs[M],rnd[M],val[M],siz[M],ct[M];
int root[N],a[N]; inline int rand()
{
static int seed=;
return seed=(int)((((seed^)+19260817ll)*19890604ll)%);
}
void update(int p){siz[p]=siz[ls[p]]+siz[rs[p]]+ct[p];}
void rturn(int &p){int t=ls[p];ls[p]=rs[t];rs[t]=p;siz[t]=siz[p];update(p);p=t;}
void lturn(int &p){int t=rs[p];rs[p]=ls[t];ls[t]=p;siz[t]=siz[p];update(p);p=t;}
void ins(int &p,int z)
{
if (!p)
{
p=++sz;
siz[p]=ct[p]=;
val[p]=z;
rnd[p]=rand();
return;
}
siz[p]++;
if (z==val[p])ct[p]++;
else if (z<val[p])
{
ins(ls[p],z);
if (rnd[ls[p]]<rnd[p]) rturn(p);
}
else
{
ins(rs[p],z);
if (rnd[rs[p]]<rnd[p]) lturn(p);
}
}
void del(int &p,int x)
{
if (p==) return;
if (val[p]==x)
{
if (ct[p]>) ct[p]--,siz[p]--;//如果有多个直接减一即可。
else
{
if (ls[p]==||rs[p]==) p=ls[p]+rs[p];//单节点或者空的话直接儿子移上来或者删去即可。
else if (rnd[ls[p]]<rnd[rs[p]]) rturn(p),del(p,x);
else lturn(p),del(p,x);
}
}
else if (x>val[p]) siz[p]--,del(rs[p],x);
else siz[p]--,del(ls[p],x);
}
void build(int p,int l,int r,int x,int z)
{
ins(root[p],z);
if (l==r) return;
int mid=(l+r)>>;
if(x<=mid)build(p<<,l,mid,x,z);
else build(p<<|,mid+,r,x,z);
}
void get_rank_sec(int p,int z)
{
if (!p) return;//没有不需要。
if (z==val[p]) ans+=siz[ls[p]];
else if (z<val[p]) get_rank_sec(ls[p],z);
else
{
ans+=siz[ls[p]]+ct[p];
get_rank_sec(rs[p],z);
}
}
void get_rank_fir(int p,int l,int r,int x,int y,int z)
{
if (l==x&&r==y)
{
get_rank_sec(root[p],z);
return;
}
int mid=(l+r)>>;
if (y<=mid) get_rank_fir(p<<,l,mid,x,y,z);
else if (x>mid) get_rank_fir(p<<|,mid+,r,x,y,z);
else get_rank_fir(p<<,l,mid,x,mid,z),get_rank_fir(p<<|,mid+,r,mid+,y,z);
}
void mid_to_find_index(int x,int y,int z)
{
int l=,r=inf,res;
while(l<=r)
{
int mid=(l+r)>>;
ans=;get_rank_fir(,,n,x,y,mid);
if(ans<=z){l=mid+;res=mid;}
else r=mid-;
}
printf("%d\n",res);
}
void modify(int p,int l,int r,int x,int yl,int xz)
{
del(root[p],yl);
ins(root[p],xz);
if (l==r) return;
int mid=(l+r)>>;
if (x<=mid)modify(p<<,l,mid,x,yl,xz);
else modify(p<<|,mid+,r,x,yl,xz);
}
void find_before_sec(int p,int z)
{
if (!p) return;
if (val[p]<z)
{
ans=max(ans,val[p]);
find_before_sec(rs[p],z);
}
else find_before_sec(ls[p],z);
}
void find_before_fir(int p,int l,int r,int x,int y,int z)
{
if (l==x&&r==y)
{
find_before_sec(root[p],z);
return;
}
int mid=(l+r)>>;
if (y<=mid) find_before_fir(p<<,l,mid,x,y,z);
else if (x>mid) find_before_fir(p<<|,mid+,r,x,y,z);
else find_before_fir(p<<,l,mid,x,mid,z),find_before_fir(p<<|,mid+,r,mid+,y,z);
}
void find_after_sec(int p,int z)
{
if(!p)return;
if(val[p]>z)
{
ans=min(val[p],ans);
find_after_sec(ls[p],z);
}
else find_after_sec(rs[p],z);
}
void find_after_fir(int p,int l,int r,int x,int y,int z)
{
if (l==x&&r==y)
{
find_after_sec(root[p],z);
return;
}
int mid=(l+r)>>;
if (y<=mid) find_after_fir(p<<,l,mid,x,y,z);
else if (x>mid) find_after_fir(p<<|,mid+,r,x,y,z);
else find_after_fir(p<<,l,mid,x,mid,z),find_after_fir(p<<|,mid+,r,mid+,y,z);
}
int main()
{
n=read(),m=read();
for (int i=;i<=n;i++)
a[i]=read(),build(,,n,i,a[i]);
while(m--)
{
int flag=read(),x,y,k;
switch(flag)
{
case :x=read(),y=read(),k=read(),ans=,get_rank_fir(,,n,x,y,k),printf("%d\n",ans);break;
case :x=read(),y=read(),k=read(),mid_to_find_index(x,y,k);break;
case :x=read(),y=read(),modify(,,n,x,a[x],y),a[x]=y;break;
case :x=read(),y=read(),k=read(),ans=,find_before_fir(,,n,x,y,k),printf("%d\n",ans);break;
case :x=read(),y=read(),k=read(),ans=inf,find_after_fir(,,n,x,y,k),printf("%d\n",ans);break;
}
}
}
bzoj3196 二逼平衡树 树套树(线段树套Treap)的更多相关文章
- BZOJ3196二逼平衡树——线段树套平衡树(treap)
此为平衡树系列最后一道:二逼平衡树您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询 ...
- bzoj3196 二逼平衡树 树状数组套线段树
题目传送门 思路:树状数组套线段树模板题. 什么是树状数组套线段树,普通的树状数组每个点都是一个权值,而这里的树状数组每个点都是一颗权值线段树,我们用前缀差分的方法求得每个区间的各种信息, 其实关键就 ...
- BZOJ3196 二逼平衡树 ZKW线段树套vector(滑稽)
我实在是不想再打一遍树状数组套替罪羊树了... 然后在普通平衡树瞎逛的时候找到了以前看过vector题解 于是我想:为啥不把平衡树换成vector呢??? 然后我又去学了一下ZKW线段树 就用ZKW线 ...
- [BZOJ3196] 二逼平衡树 [权值线段树套位置平衡树]
题面 洛咕题面 思路 没错我就是要不走寻常路! 看看那些外层位置数据结构,必须二分的,$O(n\log^3 n)$的做法吧! 看看那些cdq分治/树状数组套线段树的,空间$O(n\log^2 n)$挤 ...
- BZOJ3196 二逼平衡树 【线段树套平衡树】
题目 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查询k在区间内的前驱(前驱 ...
- luogu3380/bzoj3196 二逼平衡树 (树状数组套权值线段树)
带修改区间K大值 这题有很多做法,我的做法是树状数组套权值线段树,修改查询的时候都是按着树状数组的规则找出那log(n)个线段树根,然后一起往下做 时空都是$O(nlog^2n)$的(如果离散化了的话 ...
- bzoj3196 二逼平衡树
题目链接 平衡树系列最后一题 坑啊 10s时间限制跑了9764ms...还是要学一学bit套主席树啦... 经典的线段树套treap...至于第一发为什么要TLE(我不会告诉你treap插入的时候忘了 ...
- bzoj3196 二逼平衡树——线段树套平衡树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3196 人生中第一棵树套树! 写了一个晚上,成功卡时 9000ms+ 过了! 很要注意数组的大 ...
- BZOJ3196:二逼平衡树(线段树套Splay)
Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查询k在 ...
随机推荐
- codevs 3129 奶牛代理商IX
时间限制: 1 s 空间限制: 32000 KB 题目等级 : 白银 Silver 题目描述 Description 小X从美国回来后,成为了USACO中国区的奶牛销售代理商,专门出售质优价廉的“ ...
- js生成txt文件
HTML CODE: <div class="modal-footer"> <a onfocus="this.blur();" id=&quo ...
- Asp.Net Core 入门(八)—— Taghelper
Taghelper是一个服务端的组件,可以在Razor文件中创建和渲染HTML元素,类似于我们在Asp.Net MVC中使用的Html Taghelper.Asp.Net Core MVC内置的Tag ...
- Java的jdbc调用SQL Server存储过程Bug201906131119
SQL Server数据库存储过程,一个查询使用动态sql,另一个不使用动态sql,这种情况,jdbc可能获取不到实际查询数据,虽然数据库中执行没问题. 解决方法,都使用静态sql,或都使用动态sql ...
- css--背景和列表
背景 背景样式: background-color 设置元素的背景颜色 background-image 把图像设置为背景 background-repeat 设置背景图像是否重复及如 ...
- shelll脚本,常见的脚本题目。
[root@localhost wyb]# cat 2quan.sh #!/bin/bash #写一个脚本,先要求输入用户名,然后让他输入一个数字,输的如果是数字给输出yes,不是数字,输出no #然 ...
- bash编程的信号捕获:
bash编程的信号捕获: kill -l KILL无法捕捉: trap 'COMMAND' SIGNAL, 信号捕捉用于:在中途中止时做一些清理操作. 一. trap捕捉到信号之后,可以 ...
- 常用c++函数
strrev(str) (str为字符串)倒序输出字符串 floor(x),有时候也写做Floor(x),其功能是“向下取整”,或者说“向下舍入”,即取不大于x的最大整数(与“四舍五入”不同,下取整 ...
- Scrapy实战-新浪网分类资讯爬虫
项目要求: 爬取新浪网导航页所有下所有大类.小类.小类里的子链接,以及子链接页面的新闻内容. 什么是Scrapy框架: Scrapy是用纯Python实现一个为了爬取网站数据.提取结构性数据而编写的应 ...
- The North American Invitational Programming Contest 2018 E. Prefix Free Code
Consider nn initial strings of lower case letters, where no initial string is a prefix of any other ...