二逼平衡树 题解
时间:2019-06-13
本文章向大家介绍二逼平衡树 题解,主要包括二逼平衡树 题解使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
我 想 扇 死 自 己
void up(int x) { if(x) { size[x]=cnt[x];//我TM这行忘了 if(son[x][0])size[x]+=size[son[x][0]]; if(son[x][1])size[x]+=size[son[x][1]]; } }
4个小时!调一道模板!我敲里码!
上道splay刚因为细节打错浪费了3个小时时间,这次就又**重现了
不多说了,先把splay抄上10遍,手写!
-----------以下是正经题解----------------
第一道树套树:线段树套splay
对于线段树的每一段区间建splay维护这段的信息
在合并时:
排名相加;
前驱取max;
后继取min;
比较麻烦的是查询数值,需要二分答案.
以数值为值域进行二分,不断询问mid的排名来缩小范围。
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> using namespace std; const int N=4000005,inf=1e9; int n,m,a[N]; int root[N],son[N][3],fa[N],key[N],size[N],type,cnt[N]; void clear(int x) { if(!x)return ; fa[x]=cnt[x]=son[x][0]=son[x][1]=size[x]=key[x]=0; } int pre(int k) { int now=son[root[k]][0]; while(son[now][1])now=son[now][1]; return now; } bool judge(int x) { return son[fa[x]][1]==x; } void up(int x) { if(x) { size[x]=cnt[x]; if(son[x][0])size[x]+=size[son[x][0]]; if(son[x][1])size[x]+=size[son[x][1]]; } } void rotate(int x) { int old=fa[x],oldf=fa[old],lr=judge(x); son[old][lr]=son[x][lr^1]; fa[son[old][lr]]=old; son[x][lr^1]=old; fa[old]=x; fa[x]=oldf; if(oldf)son[oldf][son[oldf][1]==old]=x; up(old);up(x); } void splay(int k,int x) { for(int f;f=fa[x];rotate(x)) if(fa[f])rotate(judge(x)==judge(f)?f:x); root[k]=x; } void ins(int k,int x) { if(!root[k]) { type++; key[type]=x; root[k]=type; cnt[type]=size[type]=1; fa[type]=son[type][0]=son[type][1]=0; return ; } int now=root[k],f=0; while(1) { if(x==key[now]) { cnt[now]++; up(now); up(f); splay(k,now); return ; } f=now;now=son[now][key[now]<x]; if(!now) { type++; size[type]=cnt[type]=1; son[type][0]=son[type][1]=0; son[f][x>key[f]]=type; fa[type]=f; key[type]=x; up(f);splay(k,type); return ; } } } int getrank(int k,int x) { int now=root[k],ans=0; while(1) { if(!now)return ans; if(x==key[now])return (son[now][0]?size[son[now][0]]:0)+ans; else if(x>key[now]) { ans+=(son[now][0]?size[son[now][0]]:0)+cnt[now]; now=son[now][1]; } else if(x<key[now])now=son[now][0]; } } int findpos(int k,int x) { int now=root[k]; while(1) { if(x==key[now])return now; else if(x<key[now])now=son[now][0]; else now=son[now][1]; } } int findpre(int k,int x) { int now=root[k],ans=0; while(now) { if(key[now]<x) { if(ans<key[now])ans=key[now]; now=son[now][1]; } else now=son[now][0]; } return ans; } int findnxt(int k,int x) { int now=root[k],ans=inf; while(now) { if(key[now]>x) { if(ans>key[now])ans=key[now]; now=son[now][0]; } else now=son[now][1]; } return ans; } void del(int k,int x) { int now=findpos(k,x); splay(k,now); if(cnt[root[k]]>1) { cnt[root[k]]--; up(root[k]); return ; } else if(!son[root[k]][0]&&(!son[root[k]][1])) { clear(root[k]); root[k]=0; return ; } int old=root[k]; if(son[root[k]][0]*son[root[k]][1]==0) { if(!son[root[k]][0])root[k]=son[root[k]][1]; else root[k]=son[root[k]][0]; fa[root[k]]=0; clear(old); return ; } int L=pre(k); splay(k,L); son[root[k]][1]=son[old][1]; fa[son[old][1]]=root[k]; clear(old); up(root[k]); } #define ls(k) k<<1 #define rs(k) k<<1|1 void update(int k,int l,int r,int pos,int val) { ins(k,val); if(l==r)return ; int mid=l+r>>1; if(pos<=mid)update(ls(k),l,mid,pos,val); else update(rs(k),mid+1,r,pos,val); return ; } int rank(int k,int l,int r,int L,int R,int val) { if(l>=L&&r<=R) { int res=getrank(k,val); return res; } int mid=l+r>>1,res=0; if(L<=mid)res+=rank(ls(k),l,mid,L,R,val); if(R>mid)res+=rank(rs(k),mid+1,r,L,R,val); return res; } void modify(int k,int l,int r,int pos,int val) { del(k,a[pos]); ins(k,val); if(l==r)return ; int mid=l+r>>1; if(pos<=mid)modify(ls(k),l,mid,pos,val); else modify(rs(k),mid+1,r,pos,val); } int getpre(int k,int l,int r,int L,int R,int val) { if(l>=L&&r<=R)return findpre(k,val); int mid=l+r>>1,res=0; if(L<=mid)res=max(res,getpre(ls(k),l,mid,L,R,val)); if(R>mid)res=max(res,getpre(rs(k),mid+1,r,L,R,val)); return res; } int getnxt(int k,int l,int r,int L,int R,int val) { if(l>=L&&r<=R)return findnxt(k,val); int mid=l+r>>1,res=inf; if(L<=mid)res=min(res,getnxt(ls(k),l,mid,L,R,val)); if(R>mid)res=min(res,getnxt(rs(k),mid+1,r,L,R,val)); return res; } inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return x*f; } int main() { n=read();m=read(); int op,maxx=0; for(int i=1;i<=n;i++) { a[i]=read(); update(1,1,n,i,a[i]); maxx=max(maxx,a[i]); } while(m--) { op=read(); if(op==1) { int l=read(),r=read(),val=read(); printf("%d\n",rank(1,1,n,l,r,val)+1); } else if(op==2) { int l=read(),r=read(),val=read(); int L=0,R=maxx+1; while(L!=R) { int mid=L+R>>1; int res=rank(1,1,n,l,r,mid); //cout<<"***"<<res<<endl; if(res<val)L=mid+1; else R=mid; } printf("%d\n",L-1); } else if(op==3) { int pos=read(),val=read();modify(1,1,n,pos,val); a[pos]=val; maxx=max(maxx,val); } else if(op==4) { int l=read(),r=read(),val=read(); printf("%d\n",getpre(1,1,n,l,r,val)); } else if(op==5) { int l=read(),r=read(),val=read(); printf("%d\n",getnxt(1,1,n,l,r,val)); } } return 0; }
原文地址:https://www.cnblogs.com/Rorschach-XR/p/11019342.html
- 【最新TensorFlow1.4.0教程01】TF1.4.0介绍与动态图机制 Eager Execution使用
- 把插入的数据自动备份到另一个表中 ~ 语境:本地和服务器自动同步
- 数据分析小案例(三):调查问卷(python)
- CTF---Web入门第十六题 天下武功唯快不破
- 数据分析小案例(二):面包是不是变轻了(python)
- 数据分析小案例(一):商业街抽奖(python)
- Bagging算法(R语言)
- iOS @property探究(一): 基础详解你要知道的@property都在这里
- 在创建带输出参数和返回值的存储过程时---犯下的一个低级错误
- iOS block探究(二): 深入理解你要知道的block都在这里
- 使用开源人脸特征提取器进行脸部颜值评分
- iOS @property探究(二): 深入理解你要知道的@property都在这里
- iOS block探究(一): 基础详解你要知道的block都在这里
- 在不动用sp_configure的情况下,如何 =》去掉列的自增长,并保留原数据
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- OSPF 路由协议配置
- 项目实战 | 细节决定成败的渗透测试
- 构建Rasa低成本的Docker开发部署环境
- JsonPath实践(五)
- 项目实战 | 细节决定成败的渗透测试
- 工具的使用 | CobaltStrike证书修改躲避流量审查
- 一分钟学Python|Python的集合
- 遇到个小BUG之后
- 小白学PyTorch | 1 搭建一个超简单的网络
- 小白学PyTorch | 动态图与静态图的浅显理解
- Go 视图模板篇(五):模板布局和继承
- Go 视图模板篇(四):上下文感知与 XSS 攻击
- 引入 Laravel Mix 管理前端资源
- Go 视图模板篇(三):参数、管道和函数调用
- 基于独立的 Laravel Eloquent 组件编写 ORM 模型类