正题

题目链接: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-[模板]线段树分裂的更多相关文章

  1. 「Luogu P5494 【模板】线段树分裂」

    (因为没有认证,所以这道题就由Froggy上传) 线段树分裂用到的地方确实并不多,luogu上以前也没有这道模板题,所以就出了一道,实在是想不出怎么出模板了,所以这道题可能可以用一些其他的算法水过去. ...

  2. 有趣的线段树模板合集(线段树,最短/长路,单调栈,线段树合并,线段树分裂,树上差分,Tarjan-LCA,势能线段树,李超线段树)

    线段树分裂 以某个键值为中点将线段树分裂成左右两部分,应该类似Treap的分裂吧(我菜不会Treap).一般应用于区间排序. 方法很简单,就是把分裂之后的两棵树的重复的\(\log\)个节点新建出来, ...

  3. 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 ...

  4. 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)

    To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...

  5. [BZOJ4552][TJOI2016&&HEOI2016]排序(二分答案+线段树/线段树分裂与合并)

    解法一:二分答案+线段树 首先我们知道,对于一个01序列排序,用线段树维护的话可以做到单次排序复杂度仅为log级别. 这道题只有一个询问,所以离线没有意义,而一个询问让我们很自然的想到二分答案.先二分 ...

  6. [HEOI2016/TJOI2016] 排序 解题报告(二分答案/线段树分裂合并+set)

    题目链接: https://www.luogu.org/problemnew/show/P2824 题目描述: 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在 ...

  7. luoguP2824 [HEOI2016/TJOI2016]排序(线段树分裂做法)

    题意 所谓线段树分裂其实是本题的在线做法. 考虑如果我们有一个已经排好序的区间的权值线段树,那么就可以通过线段树上二分的方法得到第\(k\)个数是谁. 于是用set维护每个升序/降序区间的左右端点以及 ...

  8. BZOJ4552 HEOI2016/TJOI2016排序(线段树合并+线段树分裂)

    很久以前写过二分答案离线的做法,比较好理解.事实上这还是一个线段树合并+分裂的板子题,相比离线做法以更优的复杂度做了更多的事情.具体不说了.怎么交了一遍luogu上就跑第一了啊 #include< ...

  9. hdu3966 树链剖分点权模板+线段树区间更新/树状数组区间更新单点查询

    点权树的模板题,另外发现树状数组也是可以区间更新的.. 注意在对链进行操作时方向不要搞错 线段树版本 #include<bits/stdc++.h> using namespace std ...

  10. 【线段树】【P3372】模板-线段树

    百度百科 Definition&Solution 线段树是一种log级别的树形结构,可以处理区间修改以及区间查询问题.期望情况下,复杂度为O(nlogn). 核心思想见百度百科,线段树即将每个 ...

随机推荐

  1. Mysql生成UUID的SQL语句

    大写的UUID: SELECT UPPER(UUID()); 小写的UUID: SELECT LOWER(UUID()); SELECT UUID(); 去掉横杠的UUID: SELECT REPLA ...

  2. @NotNull-JSR-303验证

    背景 Spring Boot 引入Hibernate Validator 机制来支持 JSR-303 验证规范 实现 请求参数model类: package com.wzq.test.model; i ...

  3. CNN卷积神经网络详解

    前言   在学计算机视觉的这段时间里整理了不少的笔记,想着就把这些笔记再重新整理出来,然后写成Blog和大家一起分享.目前的计划如下(以下网络全部使用Pytorch搭建): 专题一:计算机视觉基础 介 ...

  4. WPF---数据绑定之PasswordBox绑定(八)

    一.概述 众所周知,绑定的源既可以是依赖属性也可以是普通的CLR属性,而绑定的目标只能是依赖属性. 控件PasswordBox的Password属性不是依赖属性,不可以作为绑定的目标与后台数据进行绑定 ...

  5. java包装类注意点

    Integer one = new Integer(100); Integer two = new Integer(100); Integer three = 100; Integer fore = ...

  6. java设计模式—单例模式(包含单例的破坏)

    什么是单例模式? 保证一个了类仅有一个实例,并提供一个访问它的全局访问点. 单例模式的应用场景? 网站的计数器,一般也是采用单例模式实现,否则难以同步: Web应用的配置对象的读取,一般也应用单例模式 ...

  7. CGLib浅析

    CGLib浅析 什么是CGLib CGLIB实现动态代理,并不要求被代理类必须实现接口,底层采用asm字节码生成框架生成代理类字节码(该代理类继承了被代理类). 所以被代理类一定不能定义为final ...

  8. adb 常用命令大全(7)- 其他实用功能

    屏幕截图 adb exec-out screencap -p > sc.pn 截图保存到电脑执行该命令的目录下 如果指定文件名以 .png 结尾时可以省略 -p 参数 注意 如果 adb 版本较 ...

  9. docker-compose up -d nginx 报错

    在阿里云ECS上创建nginx容器时,报错如上图. The solution: In your Dockerfile, before running any apt commands, add the ...

  10. input 只可以输入时分秒

    在html5的time中,只有时.分,没有秒. 例如<input type="time" name="user_date" /> 属性加上 step ...