bzoj 3196/ Tyvj 1730 二逼平衡树 (线段树套平衡树)
3196: Tyvj 1730 二逼平衡树
Time Limit: 10 Sec Memory Limit: 128 MB
[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
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<algorithm>
using namespace std;
#define M 3000001
#define N 50001 int id=;
int siz[M],cnt[M],key[M];
int fa[M],ch[M][];
struct TREE
{
int root,l,r;
}tr[N<<];
int data[N];
void Splay_up(int k)
{
siz[k]=siz[ch[k][]]+siz[ch[k][]]+cnt[k];
}
void rotate(int x,int &goal)
{
int y=fa[x],z=fa[y];
int l=ch[y][]==x,r=l^;
if(y==goal) goal=x;
else ch[z][ch[z][]==y]=x;
ch[y][l]=ch[x][r]; ch[x][r]=y;
fa[x]=z; fa[y]=x; fa[ch[y][l]]=y;
Splay_up(y);
}
void splay(int x,int &goal)
{
int y,z;
while(x!=goal)
{
y=fa[x]; z=fa[y];
if(y!=goal)
{
if(ch[z][]==y ^ ch[y][]==x) rotate(x,goal);
else rotate(y,goal);
}
rotate(x,goal);
Splay_up(x);
}
}
void Splay_insert(int &rt,int w)
{
if(!rt)
{
rt=++id;
siz[rt]=cnt[rt]=;
key[rt]=w;
return;
}
if(key[rt]==w) cnt[rt]++;
else if(w<key[rt]) Splay_insert(ch[rt][],w),fa[ch[rt][]]=rt;
else Splay_insert(ch[rt][],w),fa[ch[rt][]]=rt;
Splay_up(rt);
}
int Splay_getpre(int rt,int x)
{
int now=rt,ret;
while(now)
{
if(key[now]>=x) now=ch[now][];
else ret=now,now=ch[now][];
}
return ret;
}
int Splay_getsuc(int rt,int x)
{
int now=rt,ret;
while(now)
{
if(key[now]<=x) now=ch[now][];
else ret=now,now=ch[now][];
}
return ret;
}
int Splay_number(int now,int w)
{
while()
{
if(key[now]==w) return now;
if(w<key[now]) now=ch[now][];
else now=ch[now][];
}
}
void del(int & rt,int w)
{
int num=Splay_number(rt,w);
splay(num,rt);
if(cnt[num]>) cnt[num]--, siz[num]--;
else
{
int pre=Splay_getpre(rt,w);
splay(pre,rt);
ch[pre][]=ch[num][];
fa[ch[pre][]]=pre;
Splay_up(pre);
}
}
void add_dummy(int rt,int w,int d)
{
ch[rt][d]=++id; siz[rt]++;
fa[id]=rt; siz[id]=cnt[id]=; key[id]=w;
} void build(int k,int l,int r)
{
tr[k].l=l; tr[k].r=r;
if(l==r) return;
int mid=l+r>>;
build(k<<,l,mid);
build(k<<|,mid+,r);
}
void Segment_insert(int k,int pos,int w)
{
Splay_insert(tr[k].root,w);
if(tr[k].l==tr[k].r) return;
int mid=tr[k].l+tr[k].r>>;
if(pos<=mid) Segment_insert(k<<,pos,w);
else Segment_insert(k<<|,pos,w);
}
void dummy(int k)
{
int pre=Splay_getsuc(tr[k].root,-),suc=Splay_getpre(tr[k].root,1e8);
splay(pre,tr[k].root);
add_dummy(pre,-1e8-,);
splay(suc,tr[k].root);
add_dummy(suc,1e8+,);
if(tr[k].l==tr[k].r) return;
dummy(k<<); dummy(k<<|);
}
int order(int k,int opl,int opr,int w)
{
if(tr[k].l>=opl && tr[k].r<=opr)
{
int pre=Splay_getpre(tr[k].root,w);
splay(pre,tr[k].root);
return siz[ch[pre][]]+cnt[pre]-;
}
int mid=tr[k].l+tr[k].r>>,tmp=;
if(opl<=mid) tmp+=order(k<<,opl,opr,w);
if(opr>mid) tmp+=order(k<<|,opl,opr,w);
return tmp;
}
int Segment_number(int l,int r,int w)
{
int ll=,rr=1e8,mid,tmp,ans;
while(ll<=rr)
{
mid=ll+rr>>;
tmp=order(,l,r,mid);
if(tmp<w) ans=mid,ll=mid+;
else rr=mid-;
}
return ans;
}
void modify(int k,int pos,int before,int now)
{
del(tr[k].root,before);
Splay_insert(tr[k].root,now);
if(tr[k].l==tr[k].r)
{
data[tr[k].l]=now;
return;
}
int mid=tr[k].l+tr[k].r>>;
if(pos<=mid) modify(k<<,pos,before,now);
else modify(k<<|,pos,before,now);
}
int Segment_getpre(int k,int l,int r,int w)
{
if(tr[k].l>=l && tr[k].r<=r) return key[Splay_getpre(tr[k].root,w)];
int mid=tr[k].l+tr[k].r>>,tmp=-1e8-;
if(l<=mid) tmp=max(tmp,Segment_getpre(k<<,l,r,w));
if(r>mid) tmp=max(tmp,Segment_getpre(k<<|,l,r,w));
return tmp;
}
int Segment_getsuc(int k,int l,int r,int w)
{
if(tr[k].l>=l && tr[k].r<=r) return key[Splay_getsuc(tr[k].root,w)];
int mid=tr[k].l+tr[k].r>>,tmp=1e8+;
if(l<=mid) tmp=min(tmp,Segment_getsuc(k<<,l,r,w));
if(r>mid) tmp=min(tmp,Segment_getsuc(k<<|,l,r,w));
return tmp;
} int main()
{
freopen("psh.in","r",stdin);
freopen("psh.out","w",stdout);
int n,m;
scanf("%d%d",&n,&m);
build(,,n);
for(int i=;i<=n;i++)
{
scanf("%d",&data[i]);
Segment_insert(,i,data[i]);
}
dummy();
int opt,l,r,k;
while(m--)
{
scanf("%d",&opt);
if(opt==)
{
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",order(,l,r,k)+);
}
else if(opt==)
{
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",Segment_number(l,r,k));
}
else if(opt==)
{
scanf("%d%d",&l,&k);
modify(,l,data[l],k);
}
else if(opt==)
{
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",Segment_getpre(,l,r,k));
}
else
{
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",Segment_getsuc(,l,r,k));
}
}
}
bzoj 3196/ Tyvj 1730 二逼平衡树 (线段树套平衡树)的更多相关文章
- 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.... -------------------------------------------------------------------- ...
- BZOJ 3196 Tyvj 1730 二逼平衡树 树套树 线段树 treap
http://www.lydsy.com/JudgeOnline/problem.php?id=3196 http://hzwer.com/2734.html 线段树套treap,似乎splay也可以 ...
- BZOJ 3196 Tyvj 1730 二逼平衡树:线段树套splay
传送门 题意 给你一个长度为 $ n $ 有序数列 $ a $ ,进行 $ m $ 次操作,操作有如下几种: 查询 $ k $ 在区间 $ [l,r] $ 内的排名 查询区间 $ [l,r] $ 内排 ...
- BZOJ - 3196 Tyvj 1730 二逼平衡树 (线段树套treap)
题目链接 区间线段树套treap,空间复杂度$O(nlogn)$,时间复杂度除了查询区间k大是$O(log^3n)$以外都是$O(log^2n)$的. (据说线段树套线段树.树状数组套线段树也能过?) ...
- bzoj 3196 Tyvj 1730 二逼平衡树【线段树 套 splay】
四舍五入就是个暴力. 对于线段树的每个区间都开一棵按权值排序的splay 对于第二个操作,二分一下,每次查询mid的排名,复杂度 $ O(nlog(n)^{3}) $ 其余的操作都是$ O(nlog( ...
- bzoj 3196: Tyvj 1730 二逼平衡树
#include<cstdio> #include<ctime> #include<cstdlib> #include<iostream> #defin ...
- BZOJ 3196 Tyvj 1730 二逼平衡树 ——树状数组套主席树
[题目分析] 听说是树套树.(雾) 怒写树状数组套主席树,然后就Rank1了.23333 单点修改,区间查询+k大数查询=树状数组套主席树. [代码] #include <cstdio> ...
- BZOJ3196二逼平衡树——线段树套平衡树(treap)
此为平衡树系列最后一道:二逼平衡树您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询 ...
随机推荐
- java安装环境变量设置
1,依次打开:我的电脑-->属性-->高级-->环境变量 2,设置用户变量 新建 JAVA_HOME C:\Program Files\Java\j2sdk1.5.0 (JDK的安装 ...
- Thunder团队第一周 - Scrum会议6
Scrum会议6 小组名称:Thunder 项目名称:爱阅app Scrum Master:苗威 工作照片: 参会成员: 王航:http://www.cnblogs.com/wangh013/ 李传康 ...
- 20172330 2017-2018-1 《Java程序设计》第五周学习总结
20172330 2017-2018-1 <Java程序设计>第五周学习总结 教材学习内容总结 第五章 首先是对各种各种运算符的了解:刚开始以为相等就是=,还有其他一些符号都挺简单的,然后 ...
- LintCode-378.将二叉查找树转换成双链表
将二叉查找树转换成双链表 将一个二叉查找树按照中序遍历转换成双向链表. 样例 给定一个二叉查找树: 返回 1<->2<->3<->4<->5. 标签 链 ...
- MFC动态创建控件及其消息响应函数
这几天专门调研了一下MFC中如何动态创建控件及其消息响应函数. 参考帖子如下: (1)http://topic.csdn.net/u/20101204/13/5f1b1e70-2f1c-4205-ba ...
- 工具函数:cookie的添加、获取、删除
cookie是浏览器存储的命名数据,作用是保存用户的信息,这样我们就可以用这些信息来做一些事了,但是cookie容量很小,只有4kb. 下面是我总结的cookie的添加.获取.删除的函数: cooki ...
- tomcat8配置管理员后仍然报403
tomcat8配置管理员后仍然报403 修改conf/tomcat-users.xml <role rolename="manager"/> <role ro ...
- matlab怎么选取excel的特定列构成数组
例如:
- 【Python】Python 新式类介绍
本文转载自:kaka_ace's blog 我们使用 Python 开发时, 会遇到 class A 和 class A(object) 的写法, 这在 Python2 里是有概念上和功能上的区别, ...
- 【bzoj5064】B-number 数位dp
题目描述 B数的定义:能被13整除且本身包含字符串"13"的数. 例如:130和2613是B数,但是143和2639不是B数. 你的任务是计算1到n之间有多少个数是B数. 输入 输 ...