可持久化数组

日常不想放题目

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("%dn",query(rt[v],1,n,x));
			rt[i]=rt[v];
		}
	}
	return 0;
}

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

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    可持久化数组

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/191663

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月12日 下午5:47
下一篇 2023年2月12日 下午5:47

相关推荐