首页 > 其他分享 >可持久化线段树

可持久化线段树

时间:2024-05-14 16:30:40浏览次数:13  
标签:持久 cout int 线段 mid ls return

经典的数据结构。

权值线段树:

维护一个序列,然后记下每个 \(a_i\) 的出现次数,相当于线段树维护桶。

然后这样就可以轻而易举的求出 \(1-n\) 之间的第 \(k\) 小数了。原理类似于平衡数求 \(rank.\)

动态 · 可持久化

下面考虑动态的权值线段树。

\(l-r\) 查询可以理解为第 \(r\) 个线段树与 \(l-1\) 线段树的差(每个位置的差)的第 \(k\) 小数。

怎么做呢?只要建 \(n\) 个线段树就好了。但是这样的空间复杂度是 \(\mathcal{O(n^2\log n)}\) 的,不能被接受。

所以考虑新开点之后记录。

考虑到每一次加入都只会修改一条链上面的值,所以只新建那一条链上的至多 \(mathcal{O(\log n)}\) 的点不就好了。

程序

程式
#include <bits/stdc++.h>
#define ll long long
#define mid ((l+r)>>1) 
using namespace std;
const int N=2e5+10;
int rt[N<<5],s[N<<5],ls[N<<5],rs[N<<5];
int a[N],b[N];
int cnt;
int build(int l,int r){
	int u=++cnt;
	if(l==r) return ls[u]=rs[u]=0,u;
	ls[u]=build(l,mid), rs[u]=build(mid+1,r);
	return u;
}
int add(int p,int l,int r,int x){
	int u=++cnt;
	s[u]=s[p]+1, ls[u]=ls[p], rs[u]=rs[p];
	if(l==r) return u;
	if(x<=mid) ls[u]=add(ls[p],l,mid,x);
	else       rs[u]=add(rs[p],mid+1,r,x);
	return u;
}
int qry(int u,int v,int l,int r,int k){
	if(l==r) return l;
	int dlt=s[ls[u]]-s[ls[v]];
	if(dlt>=k) return qry(ls[u],ls[v],l,mid,k);
	else       return qry(rs[u],rs[v],mid+1,r,k-dlt);
}
int n,m;
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	cin>>n>>m;
	build(1,n);
	for(int i=1;i<=n;++i) cin>>b[i], a[i]=b[i];
	stable_sort(b+1,b+n+1);
	int len=unique(b+1,b+n+1)-b;
	for(int i=1;i<=n;++i) a[i]=lower_bound(b+1,b+len+1,a[i])-b;
	for(int i=1;i<=n;++i) rt[i]=add(rt[i-1],1,n,a[i]);
	while(m--){
		int l,r,k; cin>>l>>r>>k;
		cout<<b[qry(rt[r],rt[l-1],1,n,k)]<<"\n";
	}
	return 0;
} 

标签:持久,cout,int,线段,mid,ls,return
From: https://www.cnblogs.com/chihirofujisaki/p/18191576/HjtSegmentTree

相关文章

  • 洛谷 P2824 [HEOI2016/TJOI2016] 排序(二分,线段树)
    传送门解题思路据说是经典思路:把多次排序转化成二分+01序列。首先二分所求位置的数字是啥,将大于mid的数字变成1,将小于等于mid的数字变成0。这样在排序的时候就相当于统计区间里的1的个数(区间和),然后区间全部变成0或者1。也就是区间修改,区间求和,线段树可以实现。AC代码#inclu......
  • 小小redis持久化,拿捏
    前言我们先来说说什么是持久化持久化顾名思义就是数据长久保存,Redis为什么需要持久化呢,好呆的问题,Redis数据是存储在内存中的,内存数据的特点就是一旦重启就什么都没了我们将文件由内存中保存到硬盘中的这个过程,我们叫做数据保存,也就叫做持久化。但是把它保存下来不是你的目......
  • 详解Redis持久化(持久化高危漏洞利用与多种对抗方案、RDB、AOF、同步手动持久化、异步
    谨防持久化+未授权访问漏洞入侵服务器CVE编号找不到,CNVD有一个:CNVD-2015-07557(国家信息安全漏洞共享平台漏洞编号)。这是我之前写过的文章,漏洞成因、影响范围、POC与对抗方案有详解:谨防利用Redis未授权访问漏洞入侵服务器RDB(RedisDatabase、全量保存,默认方式)极简概括:通过符......
  • 雨天的尾巴(P4556 [Vani有约会] 雨天的尾巴 /【模板】线段树合并)
    1.题意简化N个点,形成一个树状结构。有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品。完成所有发放后,每个点存放最多的是哪种物品。2.思路首先这道题肯定要用先建树,然后我们可以在树上的每个节点建一个权值线段树,考虑到空间问题(每个点都有1个权值......
  • 格式和协议_数据传输和持久化
    数据格式:序列化:序列化最终的目的是为了对象可以跨平台存储和进行网络传输ProtocolBuffersParquet是一种列式存储格式,旨在提供一种高效的方式来存储和处理大型数据集 Parquet不是“运行时内存格式”,它属于文件格式Avro格式是一种远程过程调用(RPC)和数据......
  • P4839 P 哥的桶 线段树+线性基
    P4839P哥的桶线段树+线性基题目链接题意:现在有\(n\)个桶,需要支持2种操作。\(1\)\(k\)\(x\):将一个价值为\(x\)的球放进\(k\)号桶。\(2\)\(l\)\(r\):求出在\(l\)号桶到\(r\)号桶之间拿球,价值异或和最大值。思路:单点修改,区间查询。可以想到用线段树维护......
  • redis持久化
    redis持久化rdbaofvimredis.confprotected-modeyesport6379tcp-backlog511timeout0tcp-keepalive300daemonizeyespidfile/var/run/redis_6379.pidloglevelnoticelogfile"/var/log/redis/redis.log"databases16always-show-logonoset-p......
  • P3842 [TJOI2007] 线段
    洛谷-题目链接[TJOI2007]线段提示我们选择的路线是(1,1)(1,6)(2,6)(2,3)(3,3)(3,1)(4,1)(4,2)(5,2)(5,6)(6,6)(6,4)(6,6)不难计算得到,路程的总长度是24。代码代码#include<bits/stdc++.h>usingnamespacestd;constintN=2e4+5......
  • 线段树合并[学习笔记]
    线段树合并壹.什么是线段树合并?简单来说就是合并两棵线段树对于当前要合并的节点\(x,y\)如果一方为空返回另一方否则分别合并左右子树intmerge(intx,inty){if(!x||!y)returnx+y;cnt(x)+=cnt(y);//...ls(x)=merge(ls(x),ls(y));rs(x)......
  • CF-522-D-线段树
    522-D题目大意给定一个长为\(n\)的序列\(a\),现有\(q\)个查询,每个查询\(q_i\)给定\(l_i,r_i(1\lel_i,r_i\len)\),要你找出所有相等元素对\(a_x\)和\(a_y(l_i\lex,y\ler_i)\)中,绝对值\(|x-y|\)的最小值。Solution考虑三个相等的元素\(a_x,a_y,a_z(x<y<z)\),对于一个......