YSZOJ:#247. [福利]可持久化线段树 (最适合可持久化线段树入门)
题目链接:https://syzoj.com/problem/247
解题心得:
- 可持久化线段树其实就是一个线段树功能的加强版,加强在哪里呢?那就是如果一颗普通的线段树多次修改之后还能知道最开始的线段树长什么样子吗?肯定不能,如果就要问你这棵线段树在某一时刻是什么样子那能咋办。最直接的思维就是创建n棵线段树,将每一个时刻都记录下来。但是想一下时间复杂度和空间复杂度都是很大的。
- 可持久化线段树就是解决这个问题的。仔细想一想如果只修改线段树上一个叶子结点,那么对于线段树来说有改变的节点有多少个,log n 个,也就是线段树上面的一条枝。这样就可以建立一个新的根结点将需要改变的这个枝创建出来连接到新的结点上。那没有改变的节点咋办,那就值将这个新创建的节点指向上一个时刻树上没有改变的节点就行了。
//
// ┏┛ ┻━━━━━┛ ┻┓
// ┃ ┃
// ┃ ━ ┃
// ┃ ┳┛ ┗┳ ┃
// ┃ ┃
// ┃ ┻ ┃
// ┃ ┃
// ┗━┓ ┏━━━┛
// ┃ ┃ 神兽保佑
// ┃ ┃ 代码无BUG!
// ┃ ┗━━━━━━━━━┓
// ┃ ┣┓
// ┃ ┏┛
// ┗━┓ ┓ ┏━━━┳ ┓ ┏━┛
// ┃ ┫ ┫ ┃ ┫ ┫
// ┗━┻━┛ ┗━┻━┛
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e7+; int lson[maxn], rson[maxn], T[maxn];
int n,m,cnt = , sz = , node[maxn]; void updata(int root) {
node[root] = max(node[lson[root]], node[rson[root]]);
} void build_tree(int &root, int l, int r){//注意要取地质,因为是创立的新的结点
root = ++sz;
if(l == r) {
scanf("%d", &node[root]);
return ;
}
int mid = (l + r) >> ;
build_tree(lson[root], l, mid);
build_tree(rson[root], mid+, r);
updata(root);
} void init() {
scanf("%d%d",&n,&m);
build_tree(T[++cnt], , n);
} void change(int& root, int pre, int pos, int l, int r, int va){
root = ++sz;//需要改变的结点
node[root] = node[pre];
if(l == r) {
node[root] = va;
return ;
}
lson[root] = lson[pre];//新的结点的儿子直接指向前一刻树的结点
rson[root] = rson[pre];
int mid = (l + r) >> ;
if(mid >= pos)
change(lson[root], lson[pre], pos, l, mid, va);
else
change(rson[root], rson[pre], pos, mid+, r, va);
updata(root);
} int query(int root, int ql, int qr, int l, int r) {
if(l == ql && r == qr) {
return node[root];
}
int mid = (l + r) >> ;
if(mid >= qr)
return query(lson[root], ql, qr, l, mid);
else if(mid < ql)
return query(rson[root], ql, qr, mid+, r);
else
return max(query(lson[root], ql, mid, l, mid) , query(rson[root], mid+, qr, mid+, r));
} int main() {
init();
int a,b,c,d;
while(m--) {
scanf("%d%d%d%d",&a,&b,&c,&d);
if(a == ) {
change(T[++cnt], T[b], c, , n, d);//T记录第cnt课树是从哪里开始的
} else {
int ans = query(T[b], c, d, , n);
printf("%d\n",ans);
}
}
return ;
}
YSZOJ:#247. [福利]可持久化线段树 (最适合可持久化线段树入门)的更多相关文章
- BZOJ4012[HNOI2015]开店——树链剖分+可持久化线段树/动态点分治+vector
题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现她们面临着一个 ...
- 【BZOJ4137】火星商店问题(线段树分治,可持久化Trie)
[BZOJ4137]火星商店问题(线段树分治,可持久化Trie) 题面 洛谷 BZOJ权限题 题解 显然可以树套树,外层线段树,内层可持久化Trie来做. 所以我们需要更加优美的做法.--线段树分治. ...
- 洛谷 P3919 【模板】可持久化数组(可持久化线段树/平衡树)-可持久化线段树(单点更新,单点查询)
P3919 [模板]可持久化数组(可持久化线段树/平衡树) 题目背景 UPDATE : 最后一个点时间空间已经放大 标题即题意 有了可持久化数组,便可以实现很多衍生的可持久化功能(例如:可持久化并查集 ...
- 【BZOJ3673/3674】可持久化并查集/可持久化并查集加强版 可持久化线段树
[BZOJ3674]可持久化并查集加强版 Description Description:自从zkysb出了可持久化并查集后……hzwer:乱写能AC,暴力踩标程KuribohG:我不路径压缩就过了! ...
- BZOJ 3673 可持久化并查集 by zky && BZOJ 3674 可持久化并查集加强版 可持久化线段树
既然有了可持久化数组,就有可持久化并查集.. 由于上课讲过说是只能按秩合并(但是我也不确定...),所以就先写了按秩合并,相当于是维护fa[]和rk[] getf就是在这棵树中找,直到找到一个点的fa ...
- 【BZOJ】1146: [CTSC2008]网络管理Network(树链剖分+线段树套平衡树+二分 / dfs序+树状数组+主席树)
http://www.lydsy.com/JudgeOnline/problem.php?id=1146 第一种做法(时间太感人): 第二种做法(rank5,好开心) ================ ...
- 【Hihocoder 1167】 高等理论计算机科学 (树链的交,线段树或树状数组维护区间和)
[题意] 时间限制:20000ms 单点时限:1000ms 内存限制:256MB 描述 少女幽香这几天正在学习高等理论计算机科学,然而她什么也没有学会,非常痛苦.所以她出去晃了一晃,做起了一些没什么意 ...
- POJ 1804 Brainman(5种解法,好题,【暴力】,【归并排序】,【线段树单点更新】,【树状数组】,【平衡树】)
Brainman Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 10575 Accepted: 5489 Descrip ...
- Vijos P1448 校门外的树【多解,线段树,树状数组,括号序列法+暴力优化】
校门外的树 描述 校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的…… 如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两个操作: K=1,K= ...
- 【BZOJ3685】【zkw权值线段树】普通van Emde Boas树
原题传送门 因为马上要开始搞树套树了,所以学了一波权值线段树...毕竟是会点zkw线段树的,所以zkw线段树大法好! 解题思路: 介绍一下权值线段树吧,其实感觉就是线段树的本义,就是你用线段树维护了数 ...
随机推荐
- expdp指定时间戳导出防止数据不一致
expdp scott/tiger DIRECTORY=dump DUMPFILE=a.dmp FLASHBACK_TIME=“TO_TIMESTAMP(’25-08-2004 14:35:00’,’ ...
- 获取v$latch数据源实验
实验环境:Oracle Rac 11.2.0.3 首先获取v$latch的定义:通过PL/SQL或者get ddl等常规途径只能获取到v_$latch相关的视图信息.需要通过特殊方法获取v$latch ...
- Android(java)学习笔记13:线程组的概述和使用
1. Java中使用ThreadGroup来表示线程组,它可以对一批线程进行分类管理,Java允许程序直接对线程组进行控制. (1)默认情况下,所有的线程都属于主线程组. public final T ...
- Python 变量交换
# coding = utf-8 a, b = 1, 2 print 'before change' print a, b a, b = b, a print 'after change' print ...
- linux自动备份文件 并上传到远程服务器 脚本实现
(1)在服务器上创建备份目录,并赋予权限 mkdir -p /backup/bakdata #新建数据备份目录(2)完成备份脚本操作新建脚本文件 vi bakdata.sh添加 ...
- Android学习笔记_48_若水新闻客户端源码剖析
一.新闻客户端布局代码 1.1 主界面布局 使用GridView实现左右可滑动菜单项,使用标签HorizontalScrollView实现水平滚动条,将创建的GridView添加到布局文件中. < ...
- wordpress二次开发第一个jquery对比
$(document).ready(function(){ $("input").focus(function(){ $("input").css(" ...
- 整理关于 VS Code 一些小技巧:系列一
官方介绍 VisualStudioCode是一个轻量级且功能强大的源代码编辑器,它运行在桌面上,支持Windows.MacOS和Linux系统.它提供了对JavaScript.TypeScript和N ...
- Flask—04-文件上传与邮件发送(自带优化)
文件上传与邮件发送 可以按照标题分别直接粘贴对应的文件夹,运行直接用: 原生上传 模板文件 <form method="post" enctype="multipa ...
- HTML中footer固定在页面底部的若干种方法
<div class="header"><div class="main"></div></div> <d ...