首页 > 编程语言 > 详细

可持久化数组

时间:2020-01-08 17:19:59      阅读:93      评论:0      收藏:0      [点我收藏+]

日常不想放题目

Luogu P3919 【模板】可持久化数组

\(Solution\):

题目中要求可以查询历史状态,最暴力的想法是开$a[m][n]$的二维数组,每次修改暴力复制并修改,每次查询暴力扫描,时间复杂度是$O(m*n)$的,但这显然是不行的.

这个时候其实很容易想到线段树,但线段树维护的是当前状态而无法维护历史状态,一种暴力的想法是开$m$棵线段树,但这样$MLE$的风险可谓巨大。

但我们发现,因为题目修改的是一个点的值,在线段树上,会被修改的点只有$log_n$个,因此可以每次只新建这$log_n$个结点

举个例子:

一个六个数据的线段树

初始数值: 0 4 0 7 0 3(发现没什么用

建成一棵线段树:

技术分享图片

假设我们要修改第二个位置,那么被修改的也就是橙色部分:

技术分享图片

所以可以只新建这一部分节点:

技术分享图片

于是树就变成了这个亚子(

因为需要不断的新建节点,因此不能按照常规的$k<<1,k<<1|1$来记录线段树的儿子,而需要开专门的数组来记录左右儿子的编号;

我们只需要记录每次修改后的根节点$rt[i]$,在查询第$v$次操作时顺着$rt[v]$查找就好

具体实现不是很难~~(这是我第一次自己按思想自己写出来的数据结构~~

\(Code\):

#include<bits/stdc++.h>

using namespace std;

inline int read() {
	int ans=0;
	char last=‘ ‘,ch=getchar();
	while(ch>‘9‘||ch<‘0‘) last=ch,ch=getchar();
	while(ch>=‘0‘&&ch<=‘9‘) ans=(ans<<1)+(ans<<3)+ch-‘0‘,ch=getchar();
	if(last==‘-‘) ans=-ans;
	return ans;
}const int mxn=1000010;

int n,m,a[mxn];
int cntn,rt[mxn<<5]; 
struct node {
	int l,r,val;
}t[mxn<<5];

int build(int l,int r) {
	int now=++cntn;
	if(l==r) {
		t[now].val=a[l];
		return now;
	}
	int mid=(l+r)>>1;
	t[now].l=build(l,mid);
	t[now].r=build(mid+1,r);
	return now;
}

int modify(int k,int l,int r,int x,int p) {
	int now=++cntn;
	if(l==r) {
		t[now].val=p;
		return now;
	}
	int mid=(l+r)>>1;
	if(x<=mid) 
		t[now].l=modify(t[k].l,l,mid,x,p),t[now].r=t[k].r;
	else 
		t[now].r=modify(t[k].r,mid+1,r,x,p),t[now].l=t[k].l;
	return now;
}

int query(int k,int l,int r,int x) {
	if(l==r) 
		return t[k].val;
	int mid=(l+r)>>1,rtn=0;
	if(x<=mid) 
		rtn=query(t[k].l,l,mid,x);
	else 
		rtn=query(t[k].r,mid+1,r,x);
	return rtn;
}

int main() {
	n=read();
	m=read();
	for(int i=1;i<=n;i++) 
		a[i]=read();
	rt[0]=build(1,n); 
	for(int i=1,v,opt,x,y;i<=m;i++) {
		v=read();
		opt=read();
		if(opt==1) {
			x=read();
			y=read();
			rt[i]=modify(rt[v],1,n,x,y);
		} 
		if(opt==2) {
			x=read();
			printf("%d\n",query(rt[v],1,n,x));
			rt[i]=rt[v];
		}
	}
	return 0;
}

可持久化数组

原文:https://www.cnblogs.com/zhuier-xquan/p/12167232.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!