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可能为负数
 
题解
树套树,调了好久,至今都不是很清楚为什么删除节点的时候不能直接减一而必须先....说不清楚了,在代码里体现吧
 #include<cstdio>
#include<cstdlib>
#include<iostream>
using namespace std;
const int inf=,N=,M=;
int num[N],rnd[N],size[N],ls[N],rs[N],root[M],w[N],a[M];
int sz,n,m,opt,l,r;
void updata(int k){size[k]=size[ls[k]]+size[rs[k]]+w[k];}
void rturn(int &k){int t=ls[k];ls[k]=rs[t];rs[t]=k;size[t]=size[k];updata(k);k=t;}
void lturn(int &k){int t=rs[k];rs[k]=ls[t];ls[t]=k;size[t]=size[k];updata(k);k=t;}
void insert(int &k,int x){
if (!k){
k=++sz;num[k]=x;rnd[k]=rand();size[k]=w[k]=;return;
}
size[k]++;
if (x==num[k]) {w[k]++;return;}
if (x<num[k]) {insert(ls[k],x);if (rnd[ls[k]]<rnd[k]) rturn(k);}
if (x>num[k]) {insert(rs[k],x);if (rnd[rs[k]]<rnd[k]) lturn(k);}
} void del(int &k,int x){
if (!k) return;
if (num[k]==x){
if (w[k]>){w[k]--;size[k]--;return;}//就是这里,不知道为什么不是在前面直接size[k]--
if(ls[k]*rs[k]==){k=ls[k]+rs[k]; return;}
if (rnd[ls[k]]<rnd[rs[k]])rturn(k),del(k,x);
else lturn(k),del(k,x);
}
else if (num[k]>x) del(ls[k],x),size[k]--;else del(rs[k],x),size[k]--;
} void change(int pos,int x){
int k=,l=,r=n,mid=(l+r)>>;
while (l!=r){
mid=(l+r)>>;
del(root[k],a[pos]);
insert(root[k],x);
if (mid>=pos)k=k<<,r=mid;
else k=k<<|,l=mid+;
}
mid=(l+r)>>;
del(root[k],a[pos]);
insert(root[k],x);
} int solve_rank(int k,int x){
if (!k) return ;
int l=ls[k],r=rs[k];
if (num[k]==x) return size[l];
else if (num[k]>x) return solve_rank(l,x);
else return solve_rank(r,x)+size[l]+w[k];
} int get_rank(int k,int l,int r,int L,int R,int x){
if (l==L&&r==R) return (solve_rank(root[k],x));
int mid=(l+r)>>;
if (R<=mid) return get_rank(k<<,l,mid,L,R,x);
else if (L>mid) return get_rank(k<<|,mid+,r,L,R,x);
else return get_rank(k<<,l,mid,L,mid,x)+get_rank(k<<|,mid+,r,mid+,R,x);
} void build(int x,int y){
int l=,r=n,k=,mid=(l+r)>>;
while(l!=r){
insert(root[k],y);
if (mid>=x) r=mid,mid=(l+r)>>,k=k<<;
else l=mid+,mid=(l+r)>>,k=k<<|;
}
insert(root[k],y);
} int get_num(int x,int y,int z){
int l=,r=inf,ans;
while (l<=r){
int mid=(l+r)>>;
int tmp=get_rank(,,n,x,y,mid);
if (tmp<=z) ans=mid,l=mid+;//因为有重复的数字,tmp偏小
else r=mid-;
}
return ans;
} int solve_pre(int k,int x){
int l=ls[k],r=rs[k];
if (!k) return ;
if (num[k]<x) return max(num[k],solve_pre(r,x));//这里不要顺手打上=
else return solve_pre(l,x);
} int get_pre(int k,int l,int r,int L,int R,int x){
if (l==L&&r==R) return (solve_pre(root[k],x));
int mid=(l+r)>>;
if (R<=mid) return get_pre(k<<,l,mid,L,R,x);
else if (L>mid) return get_pre(k<<|,mid+,r,L,R,x);
else return max(get_pre(k<<,l,mid,L,mid,x),get_pre(k<<|,mid+,r,mid+,R,x));
} int solve_after(int k,int x){
int l=ls[k],r=rs[k];
if (!k) return inf;
if (num[k]>x) return min(num[k],solve_after(l,x));//这里不要顺手打上=*2
else return solve_after(r,x);
} int get_after(int k,int l,int r,int L,int R,int x){
if (l==L&&r==R) return (solve_after(root[k],x));
int mid=(l+r)>>;
if (R<=mid) return get_after(k<<,l,mid,L,R,x);
else if (L>mid) return get_after(k<<|,mid+,r,L,R,x);
else return min(get_after(k<<|,mid+,r,mid+,R,x),get_after(k<<,l,mid,L,mid,x));
} int main(){
freopen("sj.txt","r",stdin);
freopen("me.txt","w",stdout);
int k;
scanf("%d%d",&n,&m);
for (int i=;i<=n;i++){scanf("%d",&a[i]);build(i,a[i]);}
for (int i=;i<=m;i++){
scanf("%d%d%d",&opt,&l,&r);
if (opt!=)scanf("%d",&k);
switch(opt){
case :printf("%d\n",get_rank(,,n,l,r,k)+);break;
case :printf("%d\n",get_num(l,r,k-));break;
case :change(l,r);a[l]=r;break;
case :printf("%d\n",get_pre(,,n,l,r,k));break;
case :printf("%d\n",get_after(,,n,l,r,k));break;
}
}
}

【BZOJ3196】Tyvj 1730 二逼平衡树的更多相关文章

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

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

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

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

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

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

  4. BZOJ3196: Tyvj 1730 二逼平衡树

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

  5. [bzoj3196][Tyvj 1730][二逼平衡树] (线段树套treap)

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

  6. 【分块】bzoj3196 Tyvj 1730 二逼平衡树

    分块 或 树套树. 在每个块中维护一个有序表,查询时各种二分,全都是分块的经典操作,就不详细说了. 块的大小定为sqrt(n*log2(n))比较快. #include<cstdio> # ...

  7. 【带修莫队】【权值分块】bzoj3196 Tyvj 1730 二逼平衡树

    这题用了三种算法写: 分块+二分:O(n*sqrt(n*log(n)) 函数式权值分块:O(n*sqrt(n)) 带修莫队+权值分块:O(n5/3) 结果……复杂度越高的实际上跑得越快……最后这个竟然 ...

  8. 【函数式权值分块】【分块】bzoj3196 Tyvj 1730 二逼平衡树

    #include<cstdio> #include<cmath> #include<algorithm> using namespace std; #define ...

  9. bzoj 3196 Tyvj 1730 二逼平衡树(线段树套名次树)

    3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1807  Solved: 772[Submit][Stat ...

  10. BZOJ 3196: Tyvj 1730 二逼平衡树( 树套树 )

    这道题做法应该很多吧.... 我用了线段树套treap.... -------------------------------------------------------------------- ...

随机推荐

  1. Windows环境下安装导入tornado

    首先,一台安装并配置好了python,我的python版本的肯定是2.7,直接进入tornado的环节: 下载tornado的压缩包,我的下载地址为:https://codeload.github.c ...

  2. 核心概念 —— 服务提供者

    1.简介 服务提供者是Laravel应用启动的中心,你自己的应用以及所有Laravel的核心服务都是通过服务提供者启动. 但是,我们所谓的"启动"指的是什么?通常,这意味着注册事物 ...

  3. C#.net拖拽实现获得文件路径

    思路: 通过DragEnter事件获得被拖入窗口的“信息”(可以是若干文件,一些文字等等),  在DragDrop事件中对“信息”进行解析.        窗体的AllowDrop属性必须设置成tru ...

  4. css3 选择器记

    css3 选择器 根据所获取页面中元素的不同,把css3选择器分为五大类: 基本选择器 层次选择器 伪类选择器 动态伪类选择器 目标伪类选择器 语言伪类选择器 UI元素状态伪类选择器 结构伪类选择器 ...

  5. Ehcache(2.9.x) - API Developer Guide, Using Explicit Locking

    About Explicit Locking Ehcache contains an implementation which provides for explicit locking, using ...

  6. 产品经理常用工具Axure、Visio、Mindmanager使用解析(摘)

    如果想表现产品的业务流程,那么我建议使用Visio来绘制流程图.如果想表现产品的页面图文布局和页面的跳转关系,我建议使用axure.如果想表现产品的信息架构,我建议使用Mindmanager或Xmin ...

  7. 关于在DWZ使用ssh后台查询的几种方式

    1.查询所有记录,并以列表形式查询 DaoImpl public PageBean queryByPage(String hql, List<Object> listobj, int pa ...

  8. 值初始化-new

    程序如下#include<iostream>using namespace std; int main(){        int *a=new int(1);        int *b ...

  9. 在Apache中开启虚拟主机

    最近在自学LAMP,在Apache中尝试着开启虚拟主机的时候,遇到了挺多麻烦的,这里也顺便总结一下,在Apache中开启虚拟主机的时候,主要有下面几个步骤: 1.新建一个文件夹作为虚拟主机,用来存储网 ...

  10. Linux--fedora21 PC机安装以及拨号上网和无限上网

    最近回家,学习许久未用的linux,之前也是在培训的时候用的是 ubuntu ,这次回家查了下 fedora 最适合开发人员使用,所以就装了个试试.刚开始只能拨号上网,经过三天时间的各种搜索查找终于解 ...