P5494-[模板]线段树分裂
正题
题目链接:https://www.luogu.com.cn/problem/P5494
题目大意
给出一个可重集合要求支持
- 将集合\(p\)中在\([l,r]\)的数放到一个新的集合中
- 将集合\(t\)的所有数放入集合\(p\)中
- 在集合\(p\)中放入\(x\)个\(p\)
- 查询集合\(p\)中在\([l,r]\)区间的数
- 查询集合\(p\)中第\(k\)小的数
\(1\leq n,m\leq 2\times 10^5\)
解题思路
考虑怎么分裂,就照着一个位置\(pos\)做下去顺路一直开新节点,往左走时把右节点给新的节点就好了。
然后分裂两次再把左右合并就好了。
时间复杂度\(O(n\log n)\)
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=2e5+10,M=N<<5;
ll n,m,tot,rt[N];
ll cnt,w[M],ls[M],rs[M];
void Change(ll &x,ll L,ll R,ll pos,ll val){
if(!x)x=++cnt;
if(L==R){w[x]+=val;return;}
ll mid=(L+R)>>1;
if(pos<=mid)Change(ls[x],L,mid,pos,val);
else Change(rs[x],mid+1,R,pos,val);
w[x]=w[ls[x]]+w[rs[x]];return;
}
ll Ask(ll x,ll L,ll R,ll l,ll r){
if(!x)return 0;
if(L==l&&R==r){return w[x];}
ll mid=(L+R)>>1;
if(r<=mid)return Ask(ls[x],L,mid,l,r);
if(l>mid)return Ask(rs[x],mid+1,R,l,r);
return Ask(ls[x],L,mid,l,mid)+Ask(rs[x],mid+1,R,mid+1,r);
}
ll Bsk(ll x,ll L,ll R,ll k){
if(L==R)return L;
ll mid=(L+R)>>1;
if(w[ls[x]]>=k)return Bsk(ls[x],L,mid,k);
return Bsk(rs[x],mid+1,R,k-w[ls[x]]);
}
ll Merge(ll x,ll y){
if(!x||!y)return x+y;
ls[x]=Merge(ls[x],ls[y]);
rs[x]=Merge(rs[x],rs[y]);
w[x]=w[x]+w[y];
return x;
}
ll Split(ll x,ll L,ll R,ll pos){
if(!x)return 0;
ll y=++cnt,mid=(L+R)>>1;
if(L==R)return y;
if(pos<=mid)swap(rs[x],rs[y]);
if(L==R)return y;
if(pos<=mid)ls[y]=Split(ls[x],L,mid,pos);
else rs[y]=Split(rs[x],mid+1,R,pos);
w[x]=w[ls[x]]+w[rs[x]];w[y]=w[ls[y]]+w[rs[y]];
return y;
}
signed main()
{
scanf("%lld%lld",&n,&m);tot=1;
for(ll i=1;i<=n;i++){
ll x;scanf("%lld",&x);
if(x)Change(rt[1],0,n,i,x);
}
while(m--){
ll op;scanf("%lld",&op);
if(op==0){
ll p,x,y;scanf("%lld%lld%lld",&p,&x,&y);
++tot;rt[tot]=rt[p];
rt[p]=Split(rt[p],0,n,x-1);
rt[tot]=Merge(rt[tot],Split(rt[p],0,n,y));
swap(rt[p],rt[tot]);
}
else if(op==1){
ll p,t;scanf("%lld%lld",&p,&t);
rt[p]=Merge(rt[p],rt[t]);
}
else if(op==2){
ll p,x,q;scanf("%lld%lld%lld",&p,&x,&q);
Change(rt[p],0,n,q,x);
}
else if(op==3){
ll p,x,y;scanf("%lld%lld%lld",&p,&x,&y);
printf("%lld\n",Ask(rt[p],0,n,x,y));
}
else if(op==4){
ll p,k;scanf("%lld%lld",&p,&k);
if(w[rt[p]]<k){puts("-1");continue;}
printf("%lld\n",Bsk(rt[p],0,n,k));
}
}
return 0;
}
P5494-[模板]线段树分裂的更多相关文章
- 「Luogu P5494 【模板】线段树分裂」
(因为没有认证,所以这道题就由Froggy上传) 线段树分裂用到的地方确实并不多,luogu上以前也没有这道模板题,所以就出了一道,实在是想不出怎么出模板了,所以这道题可能可以用一些其他的算法水过去. ...
- 有趣的线段树模板合集(线段树,最短/长路,单调栈,线段树合并,线段树分裂,树上差分,Tarjan-LCA,势能线段树,李超线段树)
线段树分裂 以某个键值为中点将线段树分裂成左右两部分,应该类似Treap的分裂吧(我菜不会Treap).一般应用于区间排序. 方法很简单,就是把分裂之后的两棵树的重复的\(\log\)个节点新建出来, ...
- 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 ...
- 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)
To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...
- [BZOJ4552][TJOI2016&&HEOI2016]排序(二分答案+线段树/线段树分裂与合并)
解法一:二分答案+线段树 首先我们知道,对于一个01序列排序,用线段树维护的话可以做到单次排序复杂度仅为log级别. 这道题只有一个询问,所以离线没有意义,而一个询问让我们很自然的想到二分答案.先二分 ...
- [HEOI2016/TJOI2016] 排序 解题报告(二分答案/线段树分裂合并+set)
题目链接: https://www.luogu.org/problemnew/show/P2824 题目描述: 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在 ...
- luoguP2824 [HEOI2016/TJOI2016]排序(线段树分裂做法)
题意 所谓线段树分裂其实是本题的在线做法. 考虑如果我们有一个已经排好序的区间的权值线段树,那么就可以通过线段树上二分的方法得到第\(k\)个数是谁. 于是用set维护每个升序/降序区间的左右端点以及 ...
- BZOJ4552 HEOI2016/TJOI2016排序(线段树合并+线段树分裂)
很久以前写过二分答案离线的做法,比较好理解.事实上这还是一个线段树合并+分裂的板子题,相比离线做法以更优的复杂度做了更多的事情.具体不说了.怎么交了一遍luogu上就跑第一了啊 #include< ...
- hdu3966 树链剖分点权模板+线段树区间更新/树状数组区间更新单点查询
点权树的模板题,另外发现树状数组也是可以区间更新的.. 注意在对链进行操作时方向不要搞错 线段树版本 #include<bits/stdc++.h> using namespace std ...
- 【线段树】【P3372】模板-线段树
百度百科 Definition&Solution 线段树是一种log级别的树形结构,可以处理区间修改以及区间查询问题.期望情况下,复杂度为O(nlogn). 核心思想见百度百科,线段树即将每个 ...
随机推荐
- js判断对象的某个属性是否存在
参考:https://www.jb51.net/article/141994.htm 原始数据, [ {"name":"向阳镇","id": ...
- 【.Net】深入理解C#的装箱和拆箱
装箱和拆箱是值类型和引用类型之间相互转换是要执行的操作. 1. 装箱在值类型向引用类型转换时发生 2. 拆箱在引用类型向值类型转换时发生 光上述两句话不难理解,但是往深处了解,就需要一些篇幅来解释了 ...
- STM32+Air202+Air530+HXDZ-30102-ACC心率血氧GPS采集上传到阿里云
所有资料都在QQ群1121445919 主要功能 HXDZ-30102-ACC采集心率血氧数据 STM32通过串口将数据转发到air202模块 air202将数据上传到阿里云平台进行展示与处理 整合合 ...
- C语言格式化输出语句
%d:带符号十进制整数 : %c:单个字符: %s:字符串: %f:6位小数:float; %.2f表示小数点后精确到两位 %lf:6位小数:double;
- 【开发工具】Postman保姆级入门教程
目录 一.简单使用 1. 创建命名空间 2. 创建新集合 3. 按模块整理接口 二.使用环境变量 1. 创建环境与环境变量 2. 使用环境变量 3. 登录后自动更新环境变量 转载请注明出处 一.简单使 ...
- 集合框架2- ArrayList
其实 Java 集合框架也叫做容器,主要由两大接口派生而来,一个是 collection,主要存放对象的集合.另外一个是Map, 存储着键值对(两个对象)的映射表. 下面就来说说 List接口,Lis ...
- hash类型数据的操作指令
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.
- 服务器安装CentOS7.9系统(U盘启动方式)
一.安装环境 机房的华为GPU服务器,型号G2500,8张P4显卡,需要安装最小化的CentOS7.9操作系统,利用U盘启动的方式进行安装. 二.安装说明 虽然本环境是GPU服务器,但是安装方式同样适 ...
- MySQL——企业SQL优化方案
一.大表 (1)列多: 纵向拆分大表: create t1; insert into t1 select id, name from test; (2)行多: 根据数据存放特点和逻辑进行横向拆分大表: ...
- openswan协商流程之(七):main_inR3
主模式第六包(收包):main_inR3 1. 序言 main_inR3()函数是ISAKMP协商过程中第一阶段的最后一个报文的接收处理函数,它的作用同main_inI3_outR3()部分功能相同: ...