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;
}
}
}

最新文章

  1. GIT 基本操作
  2. 安装EPEL源
  3. 初识socket
  4. CSS3-Media Query 基础
  5. [转] 解决HttpServletResponse输出的中文乱码问题
  6. window常用软件
  7. UICollectionView未充满时也可以滚动
  8. App推广干货,排名数据分析优化效果
  9. Ejabberd源码解析前奏--安全
  10. DataGridView编辑实时生效和索引-1没有值问题
  11. STL 常用的一些容器总结
  12. 在vim中设置 &#39;打印时间&#39;的快捷键.
  13. hdu 2828 Lamp 重复覆盖
  14. 面试题:给定一个长度为N的数组,其中每个元素的取值范围都是1到N。判断数组中是否有重复的数字
  15. crontab定时任务不执行的原因
  16. git 常用的命令符
  17. mac idea sbt工程打jar包
  18. ==运算符和equals()方法的区别
  19. Tensorflow:DCGAN生成手写数字
  20. iOS项目之获取WebView的高度

热门文章

  1. (WWWWWWWWWW)codevs 3305 水果姐逛水果街Ⅱ
  2. 1898 ERROR nova.compute.manager
  3. Scalatra
  4. 【算法基础】欧几里得gcd求最大公约数
  5. shell补充知识点
  6. Quartz监听的端口
  7. Redis string类型常用操作
  8. 【Java_多线程并发编程】JUC原子类——AtomicLong原子类
  9. Spring Boot -- Idea搭建下搭建web项目
  10. CSS3-::selection