【BZOJ3196】Tyvj 1730 二逼平衡树
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
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
4
3
4
9
HINT
1.n和m的数据范围:n,m<=50000
2.序列中每个数的数据范围:[0,1e8]
- #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 二逼平衡树的更多相关文章
- bzoj3196: Tyvj 1730 二逼平衡树 树套树
地址:http://www.lydsy.com/JudgeOnline/problem.php?id=3196 题目: 3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec ...
- 【线段树套平衡树】【pb_ds】bzoj3196 Tyvj 1730 二逼平衡树
线段树套pb_ds里的平衡树,在洛谷OJ上测试,后三个测试点TLE #include<cstdio> #include<algorithm> #include<ext/p ...
- [bzoj3196]Tyvj 1730 二逼平衡树——线段树套平衡树
题目 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查 ...
- BZOJ3196: Tyvj 1730 二逼平衡树
传送门 主席树的常数蜜汁优越,在BZOJ上跑了rnk1. 做法很简单,主席树套BIT. 1-3做法很简单,第四个和第五个做法转换成前两个就行了. //BZOJ 3196 //by Cydiater / ...
- [bzoj3196][Tyvj 1730][二逼平衡树] (线段树套treap)
Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查询k在 ...
- 【分块】bzoj3196 Tyvj 1730 二逼平衡树
分块 或 树套树. 在每个块中维护一个有序表,查询时各种二分,全都是分块的经典操作,就不详细说了. 块的大小定为sqrt(n*log2(n))比较快. #include<cstdio> # ...
- 【带修莫队】【权值分块】bzoj3196 Tyvj 1730 二逼平衡树
这题用了三种算法写: 分块+二分:O(n*sqrt(n*log(n)) 函数式权值分块:O(n*sqrt(n)) 带修莫队+权值分块:O(n5/3) 结果……复杂度越高的实际上跑得越快……最后这个竟然 ...
- 【函数式权值分块】【分块】bzoj3196 Tyvj 1730 二逼平衡树
#include<cstdio> #include<cmath> #include<algorithm> using namespace std; #define ...
- bzoj 3196 Tyvj 1730 二逼平衡树(线段树套名次树)
3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1807 Solved: 772[Submit][Stat ...
- BZOJ 3196: Tyvj 1730 二逼平衡树( 树套树 )
这道题做法应该很多吧.... 我用了线段树套treap.... -------------------------------------------------------------------- ...
随机推荐
- 【转载】Kafka实现篇之消息和日志
http://blog.csdn.net/honglei915/article/details/37760631 消息格式 日志 一个叫做“my_topic”且有两个分区的的topic,它的日志有两个 ...
- 了解下SoftReference
昨天同事看到别人一段关于实现缓存功能的代码,看完之后他有点不明觉厉,哈哈,然后就给周围同事也看了下,可能之前大家都没用过SoftReference,所以并不明白是如何实现的. 于是我就把代码要了过来, ...
- DB2查看表空间大小及使用情况
1.SQL 查询(选择Schema为SYSPROC) SELECT SUBSTR(TABLESPACE_NAME,,) AS TBSPC_NAME, AS "TOTAL(MB)", ...
- Swift使用闭包表达式
Swift中的闭包表达式很灵活,其标准语法格式如下:{ (参数列表) ->返回值类型 in 语句组}其中,参数列表与函数中的参数列表形式一样,返回值类型类似于函数中的返回值类型,但不同的是 ...
- Cocoa 框架为什么采用两阶段的方式来创建对象?
对于之前一直使用C#语言的我来说,刚开始接触Objective-c来创建对象时很迷惑,为何创建对象一般情况下需要通过发送两个消息(调用两个方法)才能创建一个类实例对象(例如[[UIButton all ...
- C#解析Json格式数据小结
最近,遇到了一些不同的Json格式的数据,需要做不同处理才能转化为想要得到的结果,这里总结一下. 第一种形式:status中是{}形式,对象 string json = @"{'name': ...
- Apache 安装与配置
安装Apache 1.下载apache软件http://www.apache.org 2.安装 以管理员身份进行安装 3.设置主机名与域名 4.选择安装类型 5.自定义安装路径 6.开始安装 7.安装 ...
- 降kipmi0的CPU
echo 100 >/sys/module/ipmi_si/parameters/kipmid_max_busy_us
- Contiki学习入门之概览
Contiki是专为物联网领域而设计的开源操作系统,适用于联网嵌入式系统和无线传感器网络.由瑞典计算机科学学院的Adam Dunkels团队开发.它有以下几个特点. 1. 网络标准 contiki提供 ...
- MFC中快速应用OpenCV(转)
转载链接:http://wiki.opencv.org.cn/index.php/MFC%E4%B8%AD%E5%BF%AB%E9%80%9F%E5%BA%94%E7%94%A8OpenCV 简介和缘 ...