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

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<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 二逼平衡树 (线段树套平衡树)的更多相关文章

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

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

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

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

  3. BZOJ 3196 Tyvj 1730 二逼平衡树 树套树 线段树 treap

    http://www.lydsy.com/JudgeOnline/problem.php?id=3196 http://hzwer.com/2734.html 线段树套treap,似乎splay也可以 ...

  4. BZOJ 3196 Tyvj 1730 二逼平衡树:线段树套splay

    传送门 题意 给你一个长度为 $ n $ 有序数列 $ a $ ,进行 $ m $ 次操作,操作有如下几种: 查询 $ k $ 在区间 $ [l,r] $ 内的排名 查询区间 $ [l,r] $ 内排 ...

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

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

  6. bzoj 3196 Tyvj 1730 二逼平衡树【线段树 套 splay】

    四舍五入就是个暴力. 对于线段树的每个区间都开一棵按权值排序的splay 对于第二个操作,二分一下,每次查询mid的排名,复杂度 $ O(nlog(n)^{3}) $ 其余的操作都是$ O(nlog( ...

  7. bzoj 3196: Tyvj 1730 二逼平衡树

    #include<cstdio> #include<ctime> #include<cstdlib> #include<iostream> #defin ...

  8. BZOJ 3196 Tyvj 1730 二逼平衡树 ——树状数组套主席树

    [题目分析] 听说是树套树.(雾) 怒写树状数组套主席树,然后就Rank1了.23333 单点修改,区间查询+k大数查询=树状数组套主席树. [代码] #include <cstdio> ...

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

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

随机推荐

  1. 二:HDFS 命令指南

    命令具体选项请参考: http://hadoop.apache.org/docs/r2.6.3/hadoop-project-dist/hadoop-hdfs/HDFSCommands.html   ...

  2. Tarball——以源代码的方式安装软件

    一.Tarball文件 形成:将软件的所有源码文件先以tar打包,然后再以压缩技术(如gzip)来压缩.因为源码文件很大. 描述:一个软件包,解压缩后得到源代码文件.检测程序文件.软件的简易说明与安装 ...

  3. python模拟SQL语句操作文件

    1.需求 在文本界面输入SQL语句,查询相应的数据,例如输入下面的语句 print(''' 支持大小写的SQL语句查询,大写或者小写都可以 1. select * from db1.emp 2. se ...

  4. Qt单元测试(QTestLib)

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:Qt单元测试(QTestLib)     本文地址:http://techieliang.co ...

  5. 判断滚动条滚动到document底部

    滚动条没有实际的高度.只是为了呈现效果才在外型上面有长度. 在js当中也没有提供滚动条的高度API. 参考了网上有关资料:判断滚动条到底部的基本逻辑是滚动条滚动的高度加上视口的高度,正好是docume ...

  6. Thread.Sleep(0)

    理解Thread.Sleep函数 我们可能经常会用到 Thread.Sleep 函数来使线程挂起一段时间.那么你有没有正确的理解这个函数的用法呢? 思考下面这两个问题: 1.假设现在是 2008-4- ...

  7. 【EF】Entity Framework Core 2.0 特性介绍和使用指南

    阅读目录 前言 获取和使用 新特性 项目升级和核心API变化 下一步计划 遗憾的地方 回到目录 前言 这是.Net Core 2.0生态生态介绍的最后一篇,EF一直是我喜欢的一个ORM框架,随着版本升 ...

  8. BZOJ4869 六省联考2017相逢是问候(线段树+欧拉函数)

    由扩展欧拉定理,a^(a^(a^(……^x)))%p中x作为指数的模数应该是φ(φ(φ(φ(……p)))),而p取log次φ就会变为1,也即每个位置一旦被修改一定次数后就会变为定值.线段树维护区间剩余 ...

  9. CentOS 设置环境变量

    1. 查看环境变量,echo 命令用于在终端输出字符串或变量提取后的值,格式为“echo [字符串 | $变量]” echo $PATH /usr/local/bin:/usr/bin:/usr/lo ...

  10. [BZOJ4589]Hard Nim

    description BZOJ 题意:\(n\)堆式子,每堆石子数量为\(\le m\)的质数,对于每一个局面玩\(Nim\)游戏,求后手必胜的方案数. data range \[n\le 10^9 ...