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.查询 ...
随机推荐
- 冥冥中转到了mac 上进行开发
2013年愚人节前我的开发环境情况 我是一个有着15年windows使用经历的老programer,如果算上dos那还可以加两年.当过小企业网管,做过十二年的开发工作(直到老死,~_~).这期间当然也 ...
- hadoop参数(未完).md
我X,有违禁词.麻烦提醒一下哪个词好吗?
- c#和.net区别
.net 包含两大部分:.net framework类库和公共语言运行库(CLR) .net framework类库,就是微软工程师写好的各种功能类,例如math类. 公共语言运行库:1.与操作系统进 ...
- spring 国际化i18n配置
i18n(其来源是英文单词 internationalization的首末字符i和n,18为中间的字符数)是“国际化”的简称.在资讯领域,国际化(i18n)指让产品(出版物,软件,硬件等)无需做大的改 ...
- DAY4敏捷冲刺
站立式会议 工作安排 (1)服务器配置 已完成对微信小程序登录凭证储存至云端数据库,计划使用微信接口返回的session_id进行转化返回本地,以保持登录态. (2)数据库配置 单词学习记录+用户信息 ...
- iOS- 优化与封装 APP音效的播放
1.关于音效 音效又称短音频,是一个声音文件,在应用程序中起到点缀效果,用于提升应用程序的整体用户体验. 我们手机里常见的APP几乎都少不了音效的点缀. 显示实现音效并不复杂,但对我们App很 ...
- css那些事儿2 盒子模型
盒子模型是网页元素所占据页面窗口的矩形范围,是网页布局的核心基础之一,这里的盒子模型与我们平常收到的包裹类似. 一个包裹从内到外,分为真实物品部分,物品与外壳之间的填充区,外壳的厚度,当多个包裹放置在 ...
- Combobox的使用,日期选择器
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- 含html转义字符编码(四)转换--python
在抓取下来的网页源码显示的是如下的内容,而不是可读性的汉字 (当然,如果是在Web页面上展示,则实体会自动被浏览器转为原字符,正常显示) 经查资料后得知, 在网页中以四开头的是HTML实体,具体什么是 ...
- SIM卡是什么意思?你所不知道的SIM卡知识扫盲(详解)【转】
原文链接:http://www.jb51.net/shouji/359262.html 日常我们使用手机,SIM卡是手机的必须,没有了它就不能接入网络运营商进行通信服务.SIM卡作为网络运营商对于我们 ...