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

9 6
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

2
4
3
4
9

HINT

1.n和m的数据范围:n,m<=50000

2.序列中每个数的数据范围:[0,1e8]

3.虽然原题没有,但事实上5操作的k可能为负数

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)的更多相关文章

  1. BZOJ3196二逼平衡树——线段树套平衡树(treap)

    此为平衡树系列最后一道:二逼平衡树您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询 ...

  2. bzoj3196 二逼平衡树 树状数组套线段树

    题目传送门 思路:树状数组套线段树模板题. 什么是树状数组套线段树,普通的树状数组每个点都是一个权值,而这里的树状数组每个点都是一颗权值线段树,我们用前缀差分的方法求得每个区间的各种信息, 其实关键就 ...

  3. BZOJ3196 二逼平衡树 ZKW线段树套vector(滑稽)

    我实在是不想再打一遍树状数组套替罪羊树了... 然后在普通平衡树瞎逛的时候找到了以前看过vector题解 于是我想:为啥不把平衡树换成vector呢??? 然后我又去学了一下ZKW线段树 就用ZKW线 ...

  4. [BZOJ3196] 二逼平衡树 [权值线段树套位置平衡树]

    题面 洛咕题面 思路 没错我就是要不走寻常路! 看看那些外层位置数据结构,必须二分的,$O(n\log^3 n)$的做法吧! 看看那些cdq分治/树状数组套线段树的,空间$O(n\log^2 n)$挤 ...

  5. BZOJ3196 二逼平衡树 【线段树套平衡树】

    题目 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查询k在区间内的前驱(前驱 ...

  6. luogu3380/bzoj3196 二逼平衡树 (树状数组套权值线段树)

    带修改区间K大值 这题有很多做法,我的做法是树状数组套权值线段树,修改查询的时候都是按着树状数组的规则找出那log(n)个线段树根,然后一起往下做 时空都是$O(nlog^2n)$的(如果离散化了的话 ...

  7. bzoj3196 二逼平衡树

    题目链接 平衡树系列最后一题 坑啊 10s时间限制跑了9764ms...还是要学一学bit套主席树啦... 经典的线段树套treap...至于第一发为什么要TLE(我不会告诉你treap插入的时候忘了 ...

  8. bzoj3196 二逼平衡树——线段树套平衡树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3196 人生中第一棵树套树! 写了一个晚上,成功卡时 9000ms+ 过了! 很要注意数组的大 ...

  9. BZOJ3196:二逼平衡树(线段树套Splay)

    Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查询k在 ...

随机推荐

  1. Android学习总结(四)—— Activity和 Service进行通信

    一.Activity 和 Service进行通信的基本概念 前面我们学习我生命周期里面包含了启动和停止服务的方法,虽然服务器在活动里启动,但在启动了服务之后,活动与服务基本就没有什么关系了.我们在活动 ...

  2. jquery分页组件(每页显示多少条)

    /** * 功能说明:jPager 分页插件 * 参数说明:pages:[] 分页的控件个数 @id:显示分页的div ID,@showSelectPage: 是否显示当前分页的条目过滤下拉框 * @ ...

  3. wxwidgets编译及环境配置

    wxwidgets编译及环境配置 安装步骤: 到www.CodeBlocks.org下载并安装CodeBlocks,最好下载MinGW版本的,可以省掉安装和配置GCC的麻烦. 到www.wxWidge ...

  4. Schur 三角化定理的推论

    将学习到什么 从 Schur 的酉三角化定理可以收获一批结果,在这一部分介绍重要的几个.   迹与行列式 相似矩阵具有相同的特征多项式, 从特征多项式一节中, 我们又知道,相似矩阵的迹以及行列式都是相 ...

  5. 【page-monitor 前端自动化 下篇】 实践应用

    转载文章:来源(靠谱崔小拽) 通过page-diff的初步调研和源码分析,确定page-diff在前端自动化测试和监控方面做一些事情.本篇主要介绍下,page-diff在具体的实践中的一些应用 核心d ...

  6. java socket domain name 使用域名.

    java 的 socket 依赖了 nameService.  引擎模式. 使得 socket tcp 层 具有了上层业务的能力 (应用层) Socket socket=new Socket(&quo ...

  7. MAC的睡眠模式介绍

    因为之前用的是网上流传的土法来禁止生成 sleepimage,尝到了苦头,而且2次! 大家知道 OSX 有几种睡眠模式,其中 hibernatemode 可以是 0 (传统睡眠方式,不生成 sleep ...

  8. [BZOJ] 2662: [BeiJing wc2012]冻结

    https://www.lydsy.com/JudgeOnline/problem.php?id=2662 第一次写分层图(捂脸) 一开始真的naive地建图了,T到飞起.. 可以省下建图的空间,直接 ...

  9. WINDOWS下使用Mysql 中碰到的问题记录

    问题:在cmd中输入net stop mysql反馈“服务名无效” win+R打开运行窗口,输入 services.msc 查看其中mysql的服务名,比如我的是叫做MySQL80 让我们继续回到最开 ...

  10. 如何用纯 CSS 创作一个永动的牛顿摆

    效果预览 在线演示 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/qKmGaJ 可交互视频教 ...