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. 怎样将英文版的Eclipse转为中文版的?

    =====>1.打开eclipse储存文件夹 =====>2.在eclipse文件中找到dropins文件 =====>3.把已经下载好的eclipse汉化包复制到dropins中 ...

  2. iOS perform action after period of inactivity (no user interaction)

    代码看完后感觉非常优秀 http://stackoverflow.com/questions/8085188/ios-perform-action-after-period-of-inactivity ...

  3. django 第一次运行出错

    直接运行整个项目正常,直接运行url文件报错 报错内容: E:\Python\python.exe D:/Python储存文件/ceshiweb/ceshiweb/urls.pyTraceback ( ...

  4. Asp.Net Core 入门(八)—— Taghelper

    Taghelper是一个服务端的组件,可以在Razor文件中创建和渲染HTML元素,类似于我们在Asp.Net MVC中使用的Html Taghelper.Asp.Net Core MVC内置的Tag ...

  5. JDBC连接数据库详解

    JDBC连接数据库 •创建一个以JDBC连接数据库的程序,包含7个步骤: 1.加载JDBC驱动程序: 在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Java虚拟机),这通过java.la ...

  6. 分享一个C++与Python开发的中小型通用游戏服务端框架(跨平台,开源,适合MMORPG游戏)

    在开发一款游戏项目时,在立项时我们往往会考虑或者纠结很多,比如: 1,对于开发来说:服务端和客户端应该选择什么语言?用什么协议通信才更效率?协议后期如何维护?Socket是用长连接还是短连接?TCP还 ...

  7. Linux服务器的弱口令检测及端口扫描

    一.弱口令检测--John the Ripper John the Ripper工具可以帮助我们扫描出系统中密码安全性较低的用户,并将扫描后的结果显示出来. 1.安装John the Ripper: ...

  8. java复习之基础环境

    环境基本介绍: JDK(Java Development Kit) 是 Java 语言的软件开发工具包(SDK).在JDK的安装目录下有一个jre目录,里面有两个文件夹bin和lib,在这里可以认为b ...

  9. PAT Basic 1044

    1044 火星数字 火星人是以 13 进制计数的: 地球人的 0 被火星人称为 tret. 地球人数字 1 到 12 的火星文分别为:jan, feb, mar, apr, may, jun, jly ...

  10. JS(原型和原型链)

    (学习自慕课网<前端JavaScript 面试技巧> JS(原型和原型链) 题目1.如何准确判断一个变量是数组类型 使用 instanceof 方法 题目2.写一个原型链继承的例子 实例: ...