bzoj3196 二逼平衡树——线段树套平衡树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3196
人生中第一棵树套树!
写了一个晚上,成功卡时 9000ms+ 过了!
很要注意数组的大小,因为是树*树的大小嘛!
代码如下:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int const maxn=2e6+5,nn=5e4+5,inf=1e9;//2e6!! int n,m,tot,siz[maxn],c[maxn][3],fa[maxn],key[maxn],mn,mx,a[nn]; struct N{int l,r,rt; }t[nn<<2]; void update(int x){siz[x]=siz[c[x][0]]+siz[c[x][1]]+1;} void rotate(int x) {int y=fa[x],z=fa[y],d=(c[y][1]==x);if(z!=0)c[z][c[z][1]==y]=x;fa[x]=z; fa[y]=x; fa[c[x][d^1]]=y;c[y][d]=c[x][d^1]; c[x][d^1]=y; update(y); update(x); } void splay(int x,int f)//fa[x]=f {while(fa[x]!=f){int y=fa[x],z=fa[y];if(z!=f)// z 而非 y {if((c[y][1]==x)^(c[z][1]==y)) rotate(x);else rotate(y);}rotate(x);} } int find_pre(int x,int v) {if(!x)return 0;if(key[x]>=v) return find_pre(c[x][0],v);else{int y=find_pre(c[x][1],v);if(y)return y; else return x;} } int find_k(int x,int k) { // if(!x)return 0;if(siz[c[x][0]]==k-1)return x;if(siz[c[x][0]]>k-1)return find_k(c[x][0],k);return find_k(c[x][1],k-siz[c[x][0]]-1); } int find_suc(int x,int k)//后继 {if(!x)return 0;if(key[x]<=k)return find_suc(c[x][1],k);else{int y=find_suc(c[x][0],k);if(y)return y; else return x;//说不定就是 x } } int find_Suc(int x,int k)//相等中最小的 {if(!x)return 0;if(key[x]<k)return find_Suc(c[x][1],k);else{int y=find_Suc(c[x][0],k);if(y)return y; else return x;//说不定就是 x } } int query_k(int &x,int k)//查询 k 的排名 {int p=find_Suc(x,k); splay(p,0);//相等中最小的x=p;return siz[c[p][0]]-1;// -inf } int query(int &x,int k)//二分用 {int p=find_suc(x,k); splay(p,0);x=p;return siz[c[p][0]]-1;// -inf } void insert(int &x,int v) {int p=find_pre(x,v); splay(p,0);int y=find_k(c[p][1],1); splay(y,p);//ptot++; siz[tot]=1; fa[tot]=y; key[tot]=v; c[y][0]=tot;update(y); update(p);x=p;//rt } void del(int &x,int v) {int p=find_pre(x,v); splay(p,0);int y=find_k(c[p][1],2); splay(y,p);//pfa[c[y][0]]=0; c[y][0]=0;update(y); update(p);x=p; } void build(int x,int l,int r) {t[x].l=l; t[x].r=r;t[x].rt=++tot; siz[tot]=2; fa[tot]=0; c[tot][1]=tot+1; key[tot]=-inf;tot++; siz[tot]=1; fa[tot]=tot-1; key[tot]=inf;for(int i=l;i<=r;i++)insert(t[x].rt,a[i]);if(l==r)return;int mid=(l+r)>>1;build(x<<1,l,mid); build(x<<1|1,mid+1,r); } int query_k(int x,int l,int r,int k)//查询 k 的排名 {if(t[x].l>=l && t[x].r<=r)return query_k(t[x].rt,k);//<=k 的个数 int mid=(t[x].l+t[x].r)>>1,ret=0;//不是 l,r if(mid>=l)ret+=query_k(x<<1,l,r,k);//l,r,无需 l,mid ,因为自带 t[x].l,t[x].r if(mid<r)ret+=query_k(x<<1|1,l,r,k);return ret; } int query(int x,int l,int r,int k)//二分用 //<=mid的个数 {if(t[x].l>=l && t[x].r<=r)return query(t[x].rt,k);int mid=(t[x].l+t[x].r)>>1,ret=0;//不是 l,r if(mid>=l)ret+=query(x<<1,l,r,k);if(mid<r)ret+=query(x<<1|1,l,r,k);return ret; } void modify(int x,int p,int k) {insert(t[x].rt,k); del(t[x].rt,a[p]); if(t[x].l==t[x].r)return;// int mid=(t[x].l+t[x].r)>>1;if(p<=mid)modify(x<<1,p,k);else modify(x<<1|1,p,k); } int query_pre(int x,int l,int r,int k) {if(t[x].l>=l && t[x].r<=r)return key[find_pre(t[x].rt,k)];//返回 key ,因为需要比较int mid=(t[x].l+t[x].r)>>1,ret=0;if(mid>=l)ret=max(ret,query_pre(x<<1,l,r,k));if(mid<r)ret=max(ret,query_pre(x<<1|1,l,r,k)); return ret; } int query_suc(int x,int l,int r,int k) {if(t[x].l>=l && t[x].r<=r)return key[find_suc(t[x].rt,k)];//返回 key ,因为需要比较int mid=(t[x].l+t[x].r)>>1,ret=inf;if(mid>=l)ret=min(ret,query_suc(x<<1,l,r,k));if(mid<r)ret=min(ret,query_suc(x<<1|1,l,r,k)); return ret; } int main() {scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){scanf("%d",&a[i]);mn=min(mn,a[i]); mx=max(mx,a[i]);}build(1,1,n);for(int i=1,op,l,r,k;i<=m;i++){scanf("%d",&op);if(op!=3)scanf("%d%d%d",&l,&r,&k);if(op==1)printf("%d\n",query_k(1,l,r,k)+1);//+1if(op==2){int L=mn,R=mx,ans=0;while(L<=R){int mid=(L+R)>>1;if(query(1,l,r,mid)>=k)ans=mid,R=mid-1;// >也可,因为查询的是 <=mid 的个数 else L=mid+1;}printf("%d\n",ans);}if(op==3){int pos; scanf("%d%d",&pos,&k);modify(1,pos,k);a[pos]=k;//!!! }if(op==4)printf("%d\n",query_pre(1,l,r,k));if(op==5)printf("%d\n",query_suc(1,l,r,k));}return 0; }
转载于:https://www.cnblogs.com/Zinn/p/9221949.html
bzoj3196 二逼平衡树——线段树套平衡树相关推荐
- 【BZOJ-3196】二逼平衡树 线段树 + Splay (线段树套平衡树)
3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 2271 Solved: 935 [Submit][St ...
- 树套树-线段树套平衡树
作用 线段树的作用是区间修改和查询,平衡树的作用是查询第k大,k的排名,前驱,后继.这两个结合起来,就变成了可以区间修改和查询第k大,k的排名,前驱,后继的数据结构:树套树-线段树套平衡树. 实现 先 ...
- 并不对劲的线段树套平衡树
最近很对劲的太刀流做的一道题中说树是无向连通无环图,并不对劲的片手流为了反驳他,决定与之针锋相对,就练线段无向连通无环图套平衡无向连通无环图的题. 很对劲的太刀流-> 题意非常简单,就是维护一个 ...
- 二逼平横树——线段树套平衡树
注意空间大小,以及建树时的细节 #include<cstdio> #include<algorithm> #include<iostream> using name ...
- BZOJ3196 二逼平衡树 ZKW线段树套vector(滑稽)
我实在是不想再打一遍树状数组套替罪羊树了... 然后在普通平衡树瞎逛的时候找到了以前看过vector题解 于是我想:为啥不把平衡树换成vector呢??? 然后我又去学了一下ZKW线段树 就用ZKW线 ...
- 洛谷 P3380 bzoj3196 Tyvj1730 【模板】二逼平衡树(树套树)
[模板]二逼平衡树(树套树) 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 查询k在区间内的排名 查询区间内排名为k的值 修改某一位值上的数值 查询k在 ...
- 二逼平衡树——树套树(线段树套Splay平衡树)
题面 Bzoj3196 解析 线段树和Splay两棵树套在一起,常数直逼inf,但最终侥幸过了 思路还是比较简单, 在原数组维护一个下标线段树,再在每一个线段树节点,维护一个对应区间的权值Splay. ...
- 二逼平衡树 题解(树套树)
题面 我 想 扇 死 自 己 void up(int x){if(x){size[x]=cnt[x];//我TM这行忘了if(son[x][0])size[x]+=size[son[x][0]];if ...
- 模板:二维线段树(线段树套线段树)
文章目录 问题 解析 单点修改 询问 完整代码 标记永久化 代码 所谓二维线段树,就是有两个维度的线段树 (逃) 问题 给出一个矩形 要求支持以下操作: 1.询问一个子矩形的最值 2.修改某一个单点的 ...
- 【Luogu】P3380树套树模板(线段树套Splay)
题目链接 幸甚至哉,歌以咏志. 拿下了曾经是那么遥不可及的线段树,学会了曾经高不可攀的平衡树,弄懂了装B的时候才挂在嘴边的树套树. 每道模板都是链上的一颗珠子.把它们挨个串起来,就成为我成长的历程. ...
最新文章
- 解决 json_encode 中文乱码
- android 始终显示overflow菜单
- 【Python】一文搞懂Pandas数据排序
- 我的电脑不联网,很安全,黑客:你还有风扇呢。。。
- CV与IP:基础,经典以及最近发展
- linux之tar命令使用总结
- fasync驱动异步通知机制
- 攻防世界web新手区解题 view_source / robots / backup
- SolarWinds 供应链攻击中的第四款恶意软件及其它动态
- 内部曝料——博文年会之《武林外传》
- 力扣 69. x 的平方根 三种方法
- C++实现简单钢琴(文件读取 - 播放曲谱)
- 白化滤波器matlab程序,04实验四:白化滤波器的设计实验报告
- 维和医疗分队患者信息管理系统的开发与研究
- 专访OKEX Jay Hao:期权市场的需求从何而来?
- 通过瑞利判据对显微镜物镜进行分辨率研究
- SPSS结果解读——【独立样本T检验】【方差齐性】
- java程序设计高级教程答案_Java高级程序设计实战教程答案
- ES5-ES6-ES7_字符串与JOSN格式的数据相互转换以及深度克隆新对象
- IT行业都有哪些岗位?