AC日记——[福利]可持久化线段树 cogs 2554
2554. [福利]可持久化线段树
★★☆ 输入文件:longterm_segtree.in 输出文件:longterm_segtree.out 简单对比
时间限制:3 s 内存限制:256 MB
【题目描述】
为什么说本题是福利呢?因为这是一道非常直白的可持久化线段树的练习题,目的并不是虐人,而是指导你入门可持久化数据结构。
线段树有个非常经典的应用是处理RMQ问题,即区间最大/最小值询问问题。现在我们把这个问题可持久化一下:
Q k l r 查询数列在第k个版本时,区间[l, r]上的最大值
M k p v 把数列在第k个版本时的第p个数修改为v,并产生一个新的数列版本
最开始会给你一个数列,作为第1个版本。
每次M操作会导致产生一个新的版本。修改操作可能会很多呢,如果每次都记录一个新的数列,空间和时间上都是令人无法承受的。所以我们需要可持久化数据结构:

对于最开始的版本1,我们直接建立一颗线段树,维护区间最大值。
修改操作呢?我们发现,修改只会涉及从线段树树根到目标点上一条树链上logn个节点而已,其余的节点并不会受到影响。所以对于每次修改操作,我们可以只重建修改涉及的节点即可。就像这样:

需要查询第k个版本的最大值,那就从第k个版本的树根开始,像查询普通的线段树一样查询即可。
要计算好所需空间哦
【输入格式】
第一行两个整数N, Q。N是数列的长度,Q表示询问数
第二行N个整数,是这个数列
之后Q行,每行以0或者1开头,0表示查询操作Q,1表示修改操作M,格式为
0 k l r 查询数列在第k个版本时,区间[l, r]上的最大值 或者
1 k p v 把数列在第k个版本时的第p个数修改为v,并产生一个新的数列版本
【输出格式】
对于每个M询问,输出正确答案
【样例输入】
4 5
1 2 3 4
0 1 1 4
1 1 3 5
0 2 1 3
0 2 4 4
0 1 2 4
【样例输出】
4
5
4
4
【提示】
样例解释
序列版本1: 1 2 3 4
查询版本1的[1, 4]最大值为4
修改产生版本2: 1 2 5 4
查询版本2的[1, 3]最大值为5
查询版本1的[4, 4]最大值为4
查询版本1的[2, 4]最大值为4
数据范围
N <= 10000 Q <= 100000
对于每次询问操作的版本号k保证合法,
区间[l, r]一定满足1 <= l <= r <= N
【来源】
lj出题人: sxysxy。原题见: http://syzoj.com/problem/247
思路:
这个,裸模板呀;
来,上代码:
#include <cstdio>
#include <iostream> #define maxn 40005 using namespace std; struct TreeNodeType {
int lc,rc,dis;
};
struct TreeNodeType tree[maxn*]; int if_z,n,q,root[maxn*],cnt,tot,li,ri; char Cget; inline void in(int &now)
{
now=,if_z=,Cget=getchar();
while(Cget>''||Cget<'')
{
if(Cget=='-') if_z=-;
Cget=getchar();
}
while(Cget>=''&&Cget<='')
{
now=now*+Cget-'';
Cget=getchar();
}
now*=if_z;
return ;
} void tree_build(int &now,int l,int r)
{
now=++tot;
if(l==r)
{
in(tree[now].dis);
return ;
}
int mid=(l+r)>>;
tree_build(tree[now].lc,l,mid);
tree_build(tree[now].rc,mid+,r);
if(tree[tree[now].lc].dis>tree[tree[now].rc].dis) tree[now].dis=tree[tree[now].lc].dis;
else tree[now].dis=tree[tree[now].rc].dis;
} void tree_add(int pre,int &now,int l,int r)
{
now=++tot;
if(l==r)
{
tree[now].dis=ri;
return ;
}
int mid=(l+r)>>;
if(li<=mid)
{
tree_add(tree[pre].lc,tree[now].lc,l,mid);
tree[now].rc=tree[pre].rc;
}
else
{
tree_add(tree[pre].rc,tree[now].rc,mid+,r);
tree[now].lc=tree[pre].lc;
}
if(tree[tree[now].lc].dis>tree[tree[now].rc].dis) tree[now].dis=tree[tree[now].lc].dis;
else tree[now].dis=tree[tree[now].rc].dis;
} int tree_query(int now,int l,int r)
{
if(l>=li&&r<=ri) return tree[now].dis;
int mid=(l+r)>>;
if(li>mid) return tree_query(tree[now].rc,mid+,r);
else if(ri<=mid) return tree_query(tree[now].lc,l,mid);
else return max(tree_query(tree[now].lc,l,mid),tree_query(tree[now].rc,mid+,r));
} int main()
{
freopen("longterm_segtree.in","r",stdin);
freopen("longterm_segtree.out","w",stdout);
in(n),in(q);
tree_build(root[++cnt],,n);
int type,k;
while(q--)
{
in(type);
if(type)
{
in(k),in(li),in(ri);
tree_add(root[k],root[++cnt],,n);
}
else
{
in(k),in(li),in(ri);
printf("%d\n",tree_query(root[k],,n));
}
}
return ;
}
AC日记——[福利]可持久化线段树 cogs 2554的更多相关文章
- cogs 2554. [福利]可持久化线段树
题目链接 cogs 2554. [福利]可持久化线段树 题解 没有 代码 #include<cstdio> #include<cstring> #include<algo ...
- cogs2554 [福利]可持久化线段树
cogs2554 [福利]可持久化线段树 原题链接 每次修改复制一遍就行了... 1A!!! // It is made by XZZ #include<cstdio> #include& ...
- YSZOJ:#247. [福利]可持久化线段树 (最适合可持久化线段树入门)
题目链接:https://syzoj.com/problem/247 解题心得: 可持久化线段树其实就是一个线段树功能的加强版,加强在哪里呢?那就是如果一颗普通的线段树多次修改之后还能知道最开始的线段 ...
- [COGS2554][SYZOJ247][福利]可持久化线段树
思路: 主席树模板. 注意内存的分配,原始的线段树有$2n$个结点,每次更新时最多增加$log(n)$个结点,总共有$q$次询问,所以存储结点的数组大小为$2N+q log(n)$. #include ...
- AC日记——【模板】线段树 2 洛谷 P3373
P3373 [模板]线段树 2387通过1.8K提交标签难度 提高+/省选- 提交 讨论 题解 最新讨论 更多讨论 2333最后三个点卡常数.迷之RE感觉这题很迷啊好像一共三组测试数据.友情提示:开l ...
- AC日记——【模板】线段树 1 洛谷 P3372
题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个 ...
- 【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集
3673: 可持久化并查集 by zky Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 1878 Solved: 846[Submit][Status ...
- Tsinsen A1505. 树(张闻涛) 倍增LCA,可持久化线段树,DFS序
题目:http://www.tsinsen.com/A1505 A1505. 树(张闻涛) 时间限制:1.0s 内存限制:512.0MB 总提交次数:196 AC次数:65 平均分: ...
- BZOJ 3221: [Codechef FEB13] Obserbing the tree树上询问( 可持久化线段树 + 树链剖分 )
树链剖分+可持久化线段树....这个一眼可以看出来, 因为可持久化所以写了标记永久化(否则就是区间修改的线段树的持久化..不会), 结果就写挂了, T得飞起...和管理员拿数据调后才发现= = 做法: ...
随机推荐
- Vim如何显示和关闭行号
显示行号: set nu 去除行号: set nonu
- numpy 三个点的使用[...]
numpy [...]语法简单使用 Python numpy中切片功能与列表切片类似,但功能更加强大 本文主讲numpy中[...]的简单使用,后续工作继续补充. import numpy >& ...
- leetcode-8-pointer
void deleteNode(ListNode* node) { *node = *node->next; }
- CentOS 7.0 使用 yum 安装 MariaDB 及 简单配置
1.安装MariaDB 安装命令 yum -y install MariaDB-server MariaDB-client 安装完成MariaDB,首先启动MariaDB 设置开机启动 接下来进行Ma ...
- STM8S与IAR程序常用错误
一.IAR中的重复定义问题 在自己写头文件时,要记得将常量定义在.c文件中,如果将常量定义在.h文件中,当在main.c或者其他地方包含该头文件时,会将头文件中的常量定义包 含到main.c中,同时, ...
- Android 标题栏(2)
本文来自网易云社区 作者:孙圣翔 添加ActionProvider 1.在menu菜单中添加app:actionProviderClass属性: <item android:id=&qu ...
- Maven项目下Tomcat插件选择方法
1. 进入Tomcat官网:http://tomcat.apache.org/ 选择Maven plugin 2. 选择版本 3. 查看版本对应的插件版本: 有两种方式添加:如下图所示:
- Leetcode 440.字典序第k小的数字
字典序第k小的数字 给定整数 n 和 k,找到 1 到 n 中字典序第 k 小的数字. 注意:1 ≤ k ≤ n ≤ 109. 示例 : 输入: n: 13 k: 2 输出: 10 解释: 字典序的排 ...
- Python IO多路复用select模块
多路复用的分析实例:服务端.客户端 #服务端配置 from socket import * import time import select server = socket(AF_INET, SOC ...
- Python socket粘包问题(初级解决办法)
server端配置: import socket,subprocess,struct from socket import * server=socket(AF_INET,SOCK_STREAM) s ...