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


Sample Output


HINT

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

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

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

Solution

#include <stdio.h>
#include <stdlib.h>
#define N 50010
#define inf 0x7fffffff
#define opp 0x80000000
#define mid ((x>>1)+(y>>1)+(x&y&1))
#define dmax(x,y) ((x)>(y)?(x):(y))
#define dmin(x,y) ((x)<(y)?(x):(y))
#define RG register
#define inline __inline__ __attribute__((always_inline)) inline int Rin(){
RG int x=,c=getchar(),f=;
for(;c<||c>;c=getchar())
if(!(c^))f=-;
for(;c>&&c<;c=getchar())
x=(x<<)+(x<<)+c-;
return x*f;
} int n,m,a[N]; namespace Seg{
struct Treap{
struct Nt{
Nt*ch[];
int s,w,v,r; Nt(RG int v,RG Nt*_) : v(v),r(rand()) {
s=w=;
ch[]=ch[]=_;
} inline void maintain(){
s=w+ch[]->s+ch[]->s;
}
}*root,*null; Treap(){
null=new Nt(,0x0);
null->s=null->w=;
null->r=inf;
null->ch[]=null->ch[]=null;
root=null;
} void rotate(RG Nt*&o,RG int d){
Nt*k=o->ch[^d];
o->ch[^d]=k->ch[d];
k->ch[d]=o;
o->maintain();
k->maintain();
o=k;
} void insert(RG Nt*&o,RG int v){
if(o==null){
o=new Nt(v,null);
return;
}
o->s++;
if(v==o->v)
o->w++;
else{
RG int d=v > o->v;
insert(o->ch[d],v);
if(o->ch[d]->r < o->r)
rotate(o,^d);
}
} void remove(RG Nt*&o,RG int v){
if(o==null)
return;
if(o->v==v){
if(o->w>){
o->s--;
o->w--;
return;
}
if(o->ch[]!=null && o->ch[]!=null){
RG int d=o->ch[]->r > o->ch[]->r;
rotate(o,d);
remove(o->ch[d],v);
}
else o=o->ch[o->ch[]==null];
}
else{
o->s--;
remove(o->ch[o->v < v],v);
}
if(o!=null)
o->maintain();
} inline int pre(RG int v){
RG int ans=opp;
for(RG Nt*o=root;o!=null;)
v > o->v ? (ans=dmax(ans,o->v),o=o->ch[]) : o=o->ch[];
return ans;
} inline int nxt(RG int v){
RG int ans=inf;
for(RG Nt*o=root;o!=null;)
v < o->v ? (ans=dmin(ans,o->v),o=o->ch[]) : o=o->ch[];
return ans;
} inline int rank(RG int v){
RG int ans=;
for(Nt*o=root;o!=null;){
RG int d= v==o->v? - : (o->v < v);
if(d==-){
ans+=o->ch[]->s;
break;
}
d?(ans+=o->ch[]->s+o->w,o=o->ch[]):o=o->ch[];
}
return ans;
}
}rt[N<<]; void build(RG int x,RG int y,RG int k){
for(RG int i=x;i<=y;i++)
rt[k].insert(rt[k].root,a[i]);
if(x<y){
build(x,mid,k<<);
build(mid+,y,k<<|);
}
} void modify(RG int x,RG int y,RG int k,RG int pos,RG int num){
rt[k].remove(rt[k].root,a[pos]);
rt[k].insert(rt[k].root,num);
if(x<y)
pos<=mid ? modify(x,mid,k<<,pos,num):
modify(mid+,y,k<<|,pos,num);
} int getrank(RG int x,RG int y,RG int k,RG int l,RG int r,RG int num){
if(x==l && y==r)
return rt[k].rank(num);
if(r<=mid)
return getrank(x,mid,k<<,l,r,num);
if(l>mid)
return getrank(mid+,y,k<<|,l,r,num);
return getrank(x,mid,k<<,l,mid,num)+getrank(mid+,y,k<<|,mid+,r,num);
} int getpre(RG int x,RG int y,RG int k,RG int l,RG int r,RG int num){
if(x==l && y==r)
return rt[k].pre(num);
if(r<=mid)
return getpre(x,mid,k<<,l,r,num);
if(l>mid)
return getpre(mid+,y,k<<|,l,r,num);
return dmax(getpre(x,mid,k<<,l,mid,num),getpre(mid+,y,k<<|,mid+,r,num));
} int getnxt(RG int x,RG int y,RG int k,RG int l,RG int r,RG int num){
if(x==l && y==r)
return rt[k].nxt(num);
if(r<=mid)
return getnxt(x,mid,k<<,l,r,num);
if(l>mid)
return getnxt(mid+,y,k<<|,l,r,num);
return dmin(getnxt(x,mid,k<<,l,mid,num),getnxt(mid+,y,k<<|,mid+,r,num));
} inline int getkth(RG int l,RG int r,RG int k){
RG int x=,y=1e8;
while(x<=y)
getrank(,n,,l,r,mid) < k ?
x=mid+:
y=mid-;
if(getrank(,n,,l,r,x)>=k)
x=getpre(,n,,l,r,x);
return x;
}
} int main(){
srand('K'+'a'+'i'+'b'+'a');
n=Rin(),m=Rin();
for(int i=;i<=n;i++)
a[i]=Rin();
Seg::build(,n,);
while(m--){
RG int x,y,k,c=Rin();
switch(c){
case :
x=Rin(),y=Rin(),k=Rin();
printf("%d\n",Seg::getrank(,n,,x,y,k)+);
break;
case :
x=Rin(),y=Rin(),k=Rin();
printf("%d\n",Seg::getkth(x,y,k));
break;
case :
x=Rin(),k=Rin();
Seg::modify(,n,,x,k);
a[x]=k;
break;
case :
x=Rin(),y=Rin(),k=Rin();
printf("%d\n",Seg::getpre(,n,,x,y,k));
break;
case :
x=Rin(),y=Rin(),k=Rin();
printf("%d\n",Seg::getnxt(,n,,x,y,k));
break;
default : break;
}
}
return ;
}

[bzoj3196][Tyvj 1730][二逼平衡树] (线段树套treap)的更多相关文章

  1. BZOJ - 3196 Tyvj 1730 二逼平衡树 (线段树套treap)

    题目链接 区间线段树套treap,空间复杂度$O(nlogn)$,时间复杂度除了查询区间k大是$O(log^3n)$以外都是$O(log^2n)$的. (据说线段树套线段树.树状数组套线段树也能过?) ...

  2. 【bzoj3196】Tyvj 1730 二逼平衡树 线段树套Treap

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

  3. [bzoj3196]Tyvj 1730 二逼平衡树——线段树套平衡树

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

  4. bzoj 3196 && luogu 3380 JoyOI 1730 二逼平衡树 (线段树套Treap)

    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3196 题面; 3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Se ...

  5. bzoj3196: Tyvj 1730 二逼平衡树 树套树

    地址:http://www.lydsy.com/JudgeOnline/problem.php?id=3196 题目: 3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec ...

  6. 【线段树套平衡树】【pb_ds】bzoj3196 Tyvj 1730 二逼平衡树

    线段树套pb_ds里的平衡树,在洛谷OJ上测试,后三个测试点TLE #include<cstdio> #include<algorithm> #include<ext/p ...

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

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

  8. 【BZOJ 3196】二逼平衡树 线段树套splay 模板题

    我写的是线段树套splay,网上很多人写的都是套treap,然而本蒟蒻并不会treap 奉上sth神犇的模板: //bzoj3196 二逼平衡树,支持修改某个点的值,查询区间第k小值,查询区间某个值排 ...

  9. BZOJ3196: Tyvj 1730 二逼平衡树

    传送门 主席树的常数蜜汁优越,在BZOJ上跑了rnk1. 做法很简单,主席树套BIT. 1-3做法很简单,第四个和第五个做法转换成前两个就行了. //BZOJ 3196 //by Cydiater / ...

随机推荐

  1. 如何在IIS6,7中部署ASP.NET网站(转载)

    查看web.config文件 web.config通常会放在网站的根目录,这个文件中包含了一最重要的网站运行参数.比如: connectionStrings,httpHandlers,httpModu ...

  2. Python--变量作用域

    变量作用域: 一般在函数体外定义的变量成为全局变量,在函数内部定义的变量称为局部变量. 全局变量所有作用域都可读,局部变量只能在本函数可读 函数在读取变量时,优先读取函数本身自有的局部变量,再去读全局 ...

  3. C#调用托管C++类(DLL)

    毕设是做一个网络摄像头的相关应用.界面用WPF,图像处理部分是OpenCV.没用EmguCV的原因是国内EmguCV的资料相对比较少,EmguCV虽然提供了Winform的控件,在做UI上有一定优势, ...

  4. 使用minidom来处理XML的示例(Python 学习)(转载)

    作者网站:http://www.donews.net/limodou/archive/2004/07/15/43609.aspx  一.XML的读取.在 NewEdit 中有代码片段的功能,代码片段分 ...

  5. python学习day2

    一.模块初识 python模块 模块让你能够有逻辑地组织你的Python代码段. 把相关的代码分配到一个 模块里能让你的代码更好用,更易懂. 模块也是Python对象,具有随机的名字属性用来绑定或引用 ...

  6. HDU:3368-Reversi(暴力枚举)

    Reversi Time Limit: 5000/2000 MS (Java/Others)     Memory Limit: 65536/65536 K (Java/Others)Total Su ...

  7. 获取星座的JS函数

    通过JS获取星座的函数 function getConstellation(m,d){ var s="魔羯水瓶双鱼牡羊金牛双子巨蟹狮子处女天秤天蝎射手魔羯"; var arr=[2 ...

  8. 第六十四节,html文档布局元素

    html文档布局元素 学习要点:     1.文档元素总汇     2.文档元素解析     本章主要探讨HTML5中文档元素,文档元素的主要作用是划分各个不同的内容,让整个布局清晰明快.让整个布局元 ...

  9. JavaScript的内置对象(Date日期+string字符串)基础语法总结

    1.Date日期对象可以储存任意一个日期,并且可以精确到毫秒数(1/1000 秒). 1)定义一个时间对象 : var Udate=new Date(); //注意:使用关键字new,Date()的首 ...

  10. c# socket传输struct类型

    data结构体类型 public struct datas    { public string test1; public string test2;    } //socket服务器端 publi ...