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. sql创建作业--自动执行存储过程

    创建自动执行存储过程: 1.创建参数 2.删除已有同名的作业 3. 创建作业 4.创建作业步骤 5.连接服务器 6.创建作业调度 7.启动作业 ALTER PROCEDURE dbo.sx_pro_A ...

  2. The Singapore NRIC Check Digit

    The Singapore NRIC number is made up of 7 digits and a letter behind. This letter is calculated from ...

  3. python实现微信打飞机游戏(by crossin)

    # -*- coding: utf-8 -*- import pygame from sys import exit import random pygame.init() screen = pyga ...

  4. CAD命令标志

    CAD命令标志 主标识:(常用的)ACRX_CMD_MODAL 在别的命令执行的时候该命令不会在其中执行.ACRX_CMD_TRANSPARENT 命令可以再其它命令中执行,但在该标志下ads_sss ...

  5. 设置与使用SQL Server的字符集(Collation,即排序规则)

    目录 目录 正确认识SQL Server的字符集 选择合适的SQL Server字符集 错误使用SQL Server的字符集 参考资料 正确认识SQL Server的字符集 SQL Server作为一 ...

  6. 【转】Intellij Idea识别Java Web项目

    使用maven生成一个Java项目,手动添加相应的web目录WEB_INF,web.xml等,此时idea没有自动识别为web项目,此时编辑web.xml文件会出现一些不该出现的错误,需要做的就是让i ...

  7. Luogu P3627 抢掠计划

    题目传送门 \(Tarjan\)缩点+SPFA最长路 #include<iostream> #include<cstdio> #include<cstring> # ...

  8. 使用Auto Layout中的VFL(Visual format language)--代码实现自动布局

    使用Auto Layout中的VFL(Visual format language)--代码实现自动布局 2014-12-09 10:56 编辑: zhiwupei 分类:iOS开发 来源:机智的新手 ...

  9. (12)zabbix agent 类型所有key

    zabbix服务器端通过与zabbix agent通信来获取客户端服务器的数据,agent分为两个版本,其中一个是主动一个是被动,在配置主机我们可以看到一个是agent,另一个是agent(activ ...

  10. Linux内核 ——进程管理之进程诞生(基于版本4.x)

    <奔跑吧linux内核>3.1笔记,不足之处还望大家批评指正 进程是Linux内核最基本的抽象之一,它是处于执行期的程序.它不仅局限于一段可执行代码(代码段),还包括进程需要的其他资源.在 ...