【Luogu】P3380树套树模板(线段树套Splay)
幸甚至哉,歌以咏志。
拿下了曾经是那么遥不可及的线段树,学会了曾经高不可攀的平衡树,弄懂了装B的时候才挂在嘴边的树套树。
每道模板都是链上的一颗珠子。把它们挨个串起来,就成为我成长的历程。
抒情结束开始讲题
这道题我们用线段树存平衡树的根节点。比如我们有一棵线段树

这样子。线段树的一个节点 存 它表示的那个区间 所对应的 平衡树 的根节点编号。这样每个节点都拥有一棵平衡树。是不是很炫呢?
对于操作1我们就可以把所有零散的区间里比它小的数的个数都找出来,+1就是答案啦。
对于操作2我们可以二分数,然后不断地进行操作1.
对于操作3我们用logn的时间把所有包含这个点的区间都修改一遍。
对于操作4和操作5,不多讲了。
很炫吧
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cctype>
#define mid ((l+r)>>1)
#define left (rt<<1)
#define right (rt<<1|1)
#define lson l,mid,left
#define rson mid+1,r,right using std::max;
using std::min; inline int read(){
int num=,f=;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-;
ch=getchar();
}
while(isdigit(ch)){
num=num*+ch-'';
ch=getchar();
}
return num*f;
} int s[];
int q[]; struct Node{
int e[],fa,val,size,sum;
}tree[];
int tot,point;
inline void update(int x){
tree[x].size=tree[x].sum;
if(tree[x].e[]) tree[x].size+=tree[tree[x].e[]].size;
if(tree[x].e[]) tree[x].size+=tree[tree[x].e[]].size;
}
inline void connect(int x,int fa,int how){ tree[x].fa=fa; tree[fa].e[how]=x; }
inline int iden(int x){ return x==tree[tree[x].fa].e[]; }
void rotate(int x,int rt){
int y=tree[x].fa; int r=tree[y].fa;
if(y==s[rt]) s[rt]=x;
int sony=iden(x); int sonr=iden(y);
int b=tree[x].e[sony^];
connect(b,y,sony);
connect(y,x,sony^);
connect(x,r,sonr);
update(y); update(x);
} void splay(int pos,int to,int rt){
to=tree[to].fa;
while(tree[pos].fa!=to){
if(tree[tree[pos].fa].fa==to) rotate(pos,rt);
else
if(iden(pos)==iden(tree[pos].fa)){ rotate(tree[pos].fa,rt); rotate(pos,rt); }
else { rotate(pos,rt); rotate(pos,rt); }
}
} inline int create(int val,int fa){
tree[++tot].val=val;
tree[tot].fa=fa;
tree[tot].sum=tree[tot].size=;
return tot;
} inline void Delete(int x){
tree[x].e[]=tree[x].e[]=;
if(x==tot) tot--;
} int build(int val,int rt){
point++;
if(!s[rt]){ s[rt]=create(val,); return s[rt];}
else{
int now=s[rt];
while(){
tree[now].size++;
if(val==tree[now].val){ tree[now].sum++; return now; }
int nxt=val<tree[now].val?:;
if(!tree[now].e[nxt]){
create(val,now);
tree[now].e[nxt]=tot;
return tot;
}
now=tree[now].e[nxt];
}
}
return ;
} inline void insert(int val,int rt){
int p=build(val,rt);
splay(p,s[rt],rt);
} int find(int val,int rt){
int now=s[rt];
while(now){
if(tree[now].val==val){ splay(now,s[rt],rt); return now; }
int nxt=val>tree[now].val;
if(!tree[now].e[nxt]) return ;
now=tree[now].e[nxt];
}
} void pop(int val,int rt){
int deal=find(val,rt);
if(!deal) return;
point--;
if(tree[deal].sum>){ tree[deal].sum--; tree[deal].size--; return; }
if(!tree[deal].e[]){ s[rt]=tree[deal].e[]; tree[s[rt]].fa=; }
else{
int le=tree[deal].e[];
while(tree[le].e[]) le=tree[le].e[];
splay(le,tree[deal].e[],rt);
int ri=tree[deal].e[];
connect(ri,le,); s[rt]=le;
update(le);
}
Delete(deal);
} int rank(int val,int rt){
int ans=,now=s[rt];
while(){
//printf("%d %d\n",now,tree[now].sum);
if(val<tree[now].val){
now=tree[now].e[];
if(!now) return ans;
}
else{
if(tree[now].e[]) ans+=tree[tree[now].e[]].size;
if(val==tree[now].val||!tree[now].e[]){
if(val>tree[now].val) ans+=tree[now].sum;
splay(now,s[rt],rt);
return ans;
}
ans+=tree[now].sum; now=tree[now].e[];
}
}
} inline int lower(int val,int rt){
int ans=-,now=s[rt];
while(){
if(!now) return ans;
if(tree[now].val<val&&tree[now].val>ans) ans=tree[now].val;
int nxt=val>tree[now].val?:;
now=tree[now].e[nxt];
}
} inline int upper(int val,int rt){
int ans=,now=s[rt];
while(){
if(!now) return ans;
if(tree[now].val>val&&tree[now].val<ans) ans=tree[now].val;
int nxt=val>tree[now].val?:;
now=tree[now].e[nxt];
}
} int lows(int val,int rt){
int ans=-,now=s[rt];
while(){
if(!now) return ans;
if(tree[now].val<=val&&tree[now].val>ans) ans=tree[now].val;
if(tree[now].val==val) return ans;
int nxt=val>tree[now].val?:;
now=tree[now].e[nxt];
}
} void Build(int l,int r,int rt){
if(l>r) return;
if(l==r){
insert(q[l],rt);
return;
}
Build(lson);
Build(rson);
for(int i=l;i<=r;++i) insert(q[i],rt);
return;
} int findrank(int from,int to,int num,int l,int r,int rt){
if(from<=l&&to>=r) return rank(num,rt);
int ans=;
if(from<=mid) ans+=findrank(from,to,num,lson);
if(to>mid) ans+=findrank(from,to,num,rson);
return ans;
} void Update(int o,int num,int l,int r,int rt){
pop(q[o],rt);
insert(num,rt);
if(l==r) return;
if(o<=mid) Update(o,num,lson);
else Update(o,num,rson);
} int findlower(int from,int to,int num,int l,int r,int rt){
if(from<=l&&to>=r) return lower(num,rt);
int ans=-;
if(from<=mid) ans=max(ans,findlower(from,to,num,lson));
if(to>mid) ans=max(ans,findlower(from,to,num,rson));
return ans;
} int findupper(int from,int to,int num,int l,int r,int rt){
if(from<=l&&to>=r) return upper(num,rt);
int ans=;
if(from<=mid) ans=min(ans,findupper(from,to,num,lson));
if(to>mid) ans=min(ans,findupper(from,to,num,rson));
return ans;
} int main(){
int n=read(),m=read();
for(int i=;i<=n;++i) q[i]=read();
Build(,n,);
for(register int i=;i<=m;++i){
int opt=read();
if(opt==){
int l=read(),r=read(),q=read();
printf("%d\n",findrank(l,r,q,,n,)+);
}
else if(opt==){
int l=read(),r=read(),q=read();
int a=,b=1e8,Ans=;
while(a<=b){
int m=(a+b)>>;
int x=lows(m,);
if(findrank(l,r,x,,n,)+>q) b=m-;
else{
a=m+;
Ans=x;
}
}
printf("%d\n",Ans);
}
else if(opt==){
int l=read(),r=read();
Update(l,r,,n,);
q[l]=r;
}
else if(opt==){
int l=read(),r=read(),q=read();
printf("%d\n",findlower(l,r,q,,n,));
}
else if(opt==){
int l=read(),r=read(),q=read();
printf("%d\n",findupper(l,r,q,,n,));
}
}
return ;
}
【Luogu】P3380树套树模板(线段树套Splay)的更多相关文章
- [BZOJ 3295] [luogu 3157] [CQOI2011]动态逆序对(树状数组套权值线段树)
[BZOJ 3295] [luogu 3157] [CQOI2011] 动态逆序对 (树状数组套权值线段树) 题面 给出一个长度为n的排列,每次操作删除一个数,求每次操作前排列逆序对的个数 分析 每次 ...
- hdu 1754 I Hate It (模板线段树)
http://acm.hdu.edu.cn/showproblem.php?pid=1754 I Hate It Time Limit: 9000/3000 MS (Java/Others) M ...
- BZOJ2141排队——树状数组套权值线段树(带修改的主席树)
题目描述 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家 乐和和.红星幼儿园的小朋友们排起了长长地队伍,准备吃果果.不过因为小朋友们的身高有所区别 ...
- luogu3380/bzoj3196 二逼平衡树 (树状数组套权值线段树)
带修改区间K大值 这题有很多做法,我的做法是树状数组套权值线段树,修改查询的时候都是按着树状数组的规则找出那log(n)个线段树根,然后一起往下做 时空都是$O(nlog^2n)$的(如果离散化了的话 ...
- 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)
To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...
- CF1093E Intersection of Permutations 树状数组套权值线段树
\(\color{#0066ff}{ 题目描述 }\) 给定整数 \(n\) 和两个 \(1,\dots,n\) 的排列 \(a,b\). \(m\) 个操作,操作有两种: \(1\ l_a\ r_a ...
- Dynamic Rankings(树状数组套权值线段树)
Dynamic Rankings(树状数组套权值线段树) 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[ ...
- 【bzoj3065】带插入区间K小值 替罪羊树套权值线段树
题目描述 从前有n只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力a[i].跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理性愉悦一下,查询区间k小值.他每次向它的随从伏特提出 ...
- Luogu P4246 [SHOI2008]堵塞的交通(线段树+模拟)
P4246 [SHOI2008]堵塞的交通 题意 题目描述 有一天,由于某种穿越现象作用,你来到了传说中的小人国.小人国的布局非常奇特,整个国家的交通系统可以被看成是一个\(2\)行\(C\)列的矩形 ...
- luogu P6088 [JSOI2015]字符串树 可持久化trie 线段树合并 树链剖分 trie树
LINK:字符串树 先说比较简单的正解.由于我没有从最简单的考虑答案的角度思考 所以... 下次还需要把所有角度都考察到. 求x~y的答案 考虑 求x~根+y~根-2*lca~根的答案. 那么问题变成 ...
随机推荐
- 微软爆料新型系统,Windows7,Windows10强势来袭
本系统是10月5日最新完整版本的Windows10 安装版镜像,win10正式版,更新了重要补丁,提升应用加载速度,微软和百度今天宣布达成合作,百度成为win10 Edge浏览器中国默认主页和搜索引擎 ...
- confluent 更换ip地址之后修改数据库
由于地址搬迁导致ip地址有变动,整个的confluence的服务器的ip的地址更换和对应的数据库地址更换 root@computer-PowerEdge-T30:/opt/atlassian/conf ...
- hdu 1181 深搜
中文题 深搜 许久没写鸟,卡在输入问题上... #include <iostream> #include <string> using namespace std; bool ...
- Dijkstra算法——单源最短路算法
一.介绍 迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他各个节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止. 适用于有 ...
- [已解决]gitee初次使用git clone报错
本文描述的错误按实际出现先后顺序排列,并且附上一些其他可能会出现的问题 错误1: JZKJ@DESKTOP-I7Q9QJ4 MINGW64 ~ $ git clone https://gitee.co ...
- uaf-湖湘杯2016game_学习
0x00 分析程序 根据分析,我们可以得到以下重要数据结构 0x01 发现漏洞 1.在武器使用次数耗光后,程序会把存储该武器的堆块free,在free的时候没有清空指针,造成悬挂指针 2.commen ...
- A*和IDA*介绍
\(A*\)算法是一种很神奇的搜索方法,它属于启发式搜索中的一种.A*最主要的功能当然就是用来剪枝,提高搜索的效率.A*主要的实现方法是通过一个估价函数,每次对下一步进行一个估价,根据估价出的值来决定 ...
- iOS 面试集锦
是第一篇: 1.Difference between shallow copy and deep copy? 浅复制和深复制的区别? 答案:浅层复制:只复制指向对象的指针,而不复制引用对象本身. 深层 ...
- POJ 3080 Blue Jeans、POJ 3461 Oulipo——KMP应用
题目:POJ3080 http://poj.org/problem?id=3080 题意:对于输入的文本串,输出最长的公共子串,如果长度相同,输出字典序最小的. 这题数据量很小,用暴力也是16ms,用 ...
- (30)zabbix Trapper 监控项配置
概述 zabbix获取数据有超时时间,如果一些数据需要执行比较长的时间才能获取的话,那么zabbix会出现异常,考虑到这种情况,zabbix增加了Trapper功能,客户端自己提交数据给zabbix, ...