浅谈树状数组与线段树:https://www.cnblogs.com/AKMer/p/9946944.html

浅谈\(Splay\):https://www.cnblogs.com/AKMer/p/9979592.html

题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=3196

树套树模板题,外层用一个位置线段树,内层用一个平衡树即可解决。

查第\(k\)大是谁需要在外面套一个二分。这题比较卡,反正我是勉勉强强跑过去的……

时间复杂度:\(O(nlog^3n)\)

空间复杂度:\(O(nlogn)\)

代码如下:

#include <cstdio>
#include <algorithm>
using namespace std; const int maxn=5e4+5,inf=2147483647; int a[maxn];
int n,m,mn=1e9,mx=-1e9; int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
} struct Splay {
int tot;
int son[maxn*25][2],fa[maxn*25];
int siz[maxn*25],cnt[maxn*25],val[maxn*25]; int newnode(int v) {
val[++tot]=v;
siz[tot]=cnt[tot]=1;
return tot;
} int find(int rt,int v) {
int u=rt;
while(val[u]!=v) {
if(val[u]>v) {if(son[u][0])u=son[u][0];else break;}
if(val[u]<v) {if(son[u][1])u=son[u][1];else break;}
}
return u;
} int t(int u) {
return son[fa[u]][1]==u;
} void updata(int u) {
siz[u]=siz[son[u][0]]+cnt[u]+siz[son[u][1]];
} void rotate(int u) {
int ret=t(u),f=fa[u],s=son[u][ret^1];
son[f][ret]=s;if(s)fa[s]=f;son[u][ret^1]=f;
fa[u]=fa[f];if(fa[f])son[fa[f]][t(f)]=u;
fa[f]=u;updata(f);updata(u);
} void splay(int &rt,int u) {
while(fa[u]) {
if(fa[fa[u]]) {
if(t(fa[u])!=t(u))rotate(u);
else rotate(fa[u]);
}
rotate(u);
}
rt=u;
} void ins(int &rt,int v) {
if(!rt) {rt=newnode(v);return;}
int u=find(rt,v);
if(val[u]==v) {siz[u]++,cnt[u]++,splay(rt,u);return;}
fa[newnode(v)]=u;son[u][v>val[u]]=tot;splay(rt,tot);
} int get_rk(int &rt,int v) {
int u=find(rt,v);splay(rt,u);
if(val[u]>=v)return siz[son[u][0]];
return siz[son[u][0]]+cnt[u];
} void del(int &rt,int v) {
int u=find(rt,v);splay(rt,u);
if(cnt[u]>1) {cnt[u]--,siz[u]--;return;}
if(!son[u][0]) {rt=son[u][1],fa[rt]=0;return;}
if(!son[u][1]) {rt=son[u][0],fa[rt]=0;return;}
int node=son[u][0];while(son[node][1])node=son[node][1];
fa[son[u][0]]=0;splay(rt,node);
son[node][1]=son[u][1];fa[son[u][1]]=node;
updata(node);
} int get_pre(int &rt,int v) {
int u=find(rt,v);splay(rt,u);
if(val[u]<v)return val[u];
int node=son[u][0];
while(son[node][1])node=son[node][1];
if(node)return val[node];
return -inf;
} int get_suc(int &rt,int v) {
int u=find(rt,v);splay(rt,u);
if(val[u]>v)return val[u];
int node=son[u][1];
while(son[node][0])node=son[node][0];
if(node)return val[node];
return inf;
}
}S; struct segment_tree {
int rt[maxn<<2]; void build(int p,int l,int r) {
for(int i=l;i<=r;i++)
S.ins(rt[p],a[i]);
if(l==r)return;
int mid=(l+r)>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
} int query_rk(int p,int l,int r,int L,int R,int v) {
if(L<=l&&r<=R)return S.get_rk(rt[p],v);
int mid=(l+r)>>1,res=0;
if(L<=mid)res=query_rk(p<<1,l,mid,L,R,v);
if(R>mid)res+=query_rk(p<<1|1,mid+1,r,L,R,v);
return res;
} void change(int p,int l,int r,int pos,int v_before,int v_after) {
S.del(rt[p],v_before);S.ins(rt[p],v_after);
if(l==r)return; int mid=(l+r)>>1;
if(pos<=mid)change(p<<1,l,mid,pos,v_before,v_after);
else change(p<<1|1,mid+1,r,pos,v_before,v_after);
} int query_pre(int p,int l,int r,int L,int R,int v) {
if(L<=l&&r<=R)return S.get_pre(rt[p],v);
int mid=(l+r)>>1,res=-inf;
if(L<=mid)res=max(res,query_pre(p<<1,l,mid,L,R,v));
if(R>mid)res=max(res,query_pre(p<<1|1,mid+1,r,L,R,v));
return res;
} int query_suc(int p,int l,int r,int L,int R,int v) {
if(L<=l&&r<=R)return S.get_suc(rt[p],v);
int mid=(l+r)>>1,res=inf;
if(L<=mid)res=min(res,query_suc(p<<1,l,mid,L,R,v));
if(R>mid)res=min(res,query_suc(p<<1|1,mid+1,r,L,R,v));
return res;
}
}T; int main() {
n=read(),m=read();
for(int i=1;i<=n;i++)
a[i]=read(),mn=min(mn,a[i]),mx=max(mx,a[i]);
T.build(1,1,n);
for(int i=1;i<=m;i++) {
int opt=read(),l,r,pos,k;
if(opt==3)pos=read(),k=read();
else l=read(),r=read(),k=read();
if(opt==1)printf("%d\n",T.query_rk(1,1,n,l,r,k)+1);
if(opt==2) {
int L=mn,R=mx;
while(L<R) {
int mid=(L+R+1)>>1;
int rk=T.query_rk(1,1,n,l,r,mid)+1;
if(rk>k)R=mid-1;
else L=mid;
}
printf("%d\n",L);
}
if(opt==3)T.change(1,1,n,pos,a[pos],k),a[pos]=k,mn=min(mn,k),mx=max(mx,k);
if(opt==4)printf("%d\n",T.query_pre(1,1,n,l,r,k));
if(opt==5)printf("%d\n",T.query_suc(1,1,n,l,r,k));
}
return 0;
}

BZOJ3196:二逼平衡树的更多相关文章

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

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

  2. bzoj3196 二逼平衡树 树状数组套线段树

    题目传送门 思路:树状数组套线段树模板题. 什么是树状数组套线段树,普通的树状数组每个点都是一个权值,而这里的树状数组每个点都是一颗权值线段树,我们用前缀差分的方法求得每个区间的各种信息, 其实关键就 ...

  3. bzoj3196 二逼平衡树 树套树(线段树套Treap)

    Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 4697  Solved: 1798[Submit][Status][D ...

  4. bzoj3196 二逼平衡树

    题目链接 平衡树系列最后一题 坑啊 10s时间限制跑了9764ms...还是要学一学bit套主席树啦... 经典的线段树套treap...至于第一发为什么要TLE(我不会告诉你treap插入的时候忘了 ...

  5. BZOJ3196 二逼平衡树 ZKW线段树套vector(滑稽)

    我实在是不想再打一遍树状数组套替罪羊树了... 然后在普通平衡树瞎逛的时候找到了以前看过vector题解 于是我想:为啥不把平衡树换成vector呢??? 然后我又去学了一下ZKW线段树 就用ZKW线 ...

  6. [BZOJ3196] 二逼平衡树 [权值线段树套位置平衡树]

    题面 洛咕题面 思路 没错我就是要不走寻常路! 看看那些外层位置数据结构,必须二分的,$O(n\log^3 n)$的做法吧! 看看那些cdq分治/树状数组套线段树的,空间$O(n\log^2 n)$挤 ...

  7. BZOJ3196 二逼平衡树 【线段树套平衡树】

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

  8. BZOJ3196——二逼平衡树

    1.题目大意:给你一个序列,有5种操作,都有什么呢... 1> 区间第k小 这个直接用二分+树套树做 2> 区间小于k的有多少 这个直接用树套树做 3> 单点修改 这个直接用树套树做 ...

  9. luogu3380/bzoj3196 二逼平衡树 (树状数组套权值线段树)

    带修改区间K大值 这题有很多做法,我的做法是树状数组套权值线段树,修改查询的时候都是按着树状数组的规则找出那log(n)个线段树根,然后一起往下做 时空都是$O(nlog^2n)$的(如果离散化了的话 ...

  10. BZOJ3196:二逼平衡树(线段树套Splay)

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

随机推荐

  1. ubuntu16.04--在标题栏显示网速

    有时感觉网络失去响应,就通过Ubuntu 14.04自带的系统监视器程序来查看当前网速,但是这样很不方便,遂打算让网速显示在标题栏,那样就随时可直观的看到.一番搜索尝试后,成功实现!同时也实现了CPU ...

  2. python学习(三)数字类型示例

    奶奶的报了这个错,我以为可以像java中字符串加数字的嘛 Traceback (most recent call last):   File "./number.py", line ...

  3. 请实现一个函数用来匹配包括'.'和'*'的正则表达式。模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但是与"aa.a"和"ab*a"均不匹配

    // test20.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> #include< ...

  4. 【demo练习四】:WPF用户控件案例

    首先,新建vs中“用户控件(WPF)”,右键项目名 =>"添加"按钮 => 选择“新建项”. 然后选择“用户控件(WPF)” => 起名字 => 点击“添加 ...

  5. Nginx 经验小结

    chmod 777 永远不要 使用 777,有时候可以懒惰的解决权限问题, 但是它同样也表示你没有线索去解决权限问题,你只是在碰运气. 你应该检查整个路径的权限,并思考发生了什么事情. 把 root ...

  6. pycharm连git和gitee

    http://www.cnblogs.com/feixuelove1009/p/5955332.html https://www.58jb.com/html/171.html

  7. Angular入门(二) 服务

    目的:为了不再把相同的代码复制一遍又一遍,我们要创建一个单一的可复用的数据服务,并且把它注入到需要它的那些组件中. ※  文件命名约定:服务名称的小写形式(基本名),加上.service后缀,如果服务 ...

  8. 九度OJ 1144:Freckles(斑点) (最小生成树)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:1538 解决:760 题目描述: In an episode of the Dick Van Dyke show, little Richi ...

  9. ajax实时获取下拉数据

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> ajax ...

  10. ME11创建信息记录 Function

    转自 http://blog.csdn.net/zeewjj/article/details/7941530  CALL FUNCTION 'ME_DIRECT_INPUT_INFORECORD' D ...