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的更多相关文章

  1. cogs 2554. [福利]可持久化线段树

    题目链接 cogs 2554. [福利]可持久化线段树 题解 没有 代码 #include<cstdio> #include<cstring> #include<algo ...

  2. cogs2554 [福利]可持久化线段树

    cogs2554 [福利]可持久化线段树 原题链接 每次修改复制一遍就行了... 1A!!! // It is made by XZZ #include<cstdio> #include& ...

  3. YSZOJ:#247. [福利]可持久化线段树 (最适合可持久化线段树入门)

    题目链接:https://syzoj.com/problem/247 解题心得: 可持久化线段树其实就是一个线段树功能的加强版,加强在哪里呢?那就是如果一颗普通的线段树多次修改之后还能知道最开始的线段 ...

  4. [COGS2554][SYZOJ247][福利]可持久化线段树

    思路: 主席树模板. 注意内存的分配,原始的线段树有$2n$个结点,每次更新时最多增加$log(n)$个结点,总共有$q$次询问,所以存储结点的数组大小为$2N+q log(n)$. #include ...

  5. AC日记——【模板】线段树 2 洛谷 P3373

    P3373 [模板]线段树 2387通过1.8K提交标签难度 提高+/省选- 提交 讨论 题解 最新讨论 更多讨论 2333最后三个点卡常数.迷之RE感觉这题很迷啊好像一共三组测试数据.友情提示:开l ...

  6. AC日记——【模板】线段树 1 洛谷 P3372

    题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个 ...

  7. 【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集

    3673: 可持久化并查集 by zky Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 1878  Solved: 846[Submit][Status ...

  8. Tsinsen A1505. 树(张闻涛) 倍增LCA,可持久化线段树,DFS序

    题目:http://www.tsinsen.com/A1505 A1505. 树(张闻涛) 时间限制:1.0s   内存限制:512.0MB    总提交次数:196   AC次数:65   平均分: ...

  9. BZOJ 3221: [Codechef FEB13] Obserbing the tree树上询问( 可持久化线段树 + 树链剖分 )

    树链剖分+可持久化线段树....这个一眼可以看出来, 因为可持久化所以写了标记永久化(否则就是区间修改的线段树的持久化..不会), 结果就写挂了, T得飞起...和管理员拿数据调后才发现= = 做法: ...

随机推荐

  1. Vim如何显示和关闭行号

    显示行号: set nu 去除行号: set nonu

  2. numpy 三个点的使用[...]

    numpy [...]语法简单使用 Python numpy中切片功能与列表切片类似,但功能更加强大 本文主讲numpy中[...]的简单使用,后续工作继续补充. import numpy >& ...

  3. leetcode-8-pointer

    void deleteNode(ListNode* node) { *node = *node->next; }

  4. CentOS 7.0 使用 yum 安装 MariaDB 及 简单配置

    1.安装MariaDB 安装命令 yum -y install MariaDB-server MariaDB-client 安装完成MariaDB,首先启动MariaDB 设置开机启动 接下来进行Ma ...

  5. STM8S与IAR程序常用错误

    一.IAR中的重复定义问题 在自己写头文件时,要记得将常量定义在.c文件中,如果将常量定义在.h文件中,当在main.c或者其他地方包含该头文件时,会将头文件中的常量定义包 含到main.c中,同时, ...

  6. Android 标题栏(2)

    本文来自网易云社区 作者:孙圣翔 添加ActionProvider 1.在menu菜单中添加app:actionProviderClass属性: <item     android:id=&qu ...

  7. Maven项目下Tomcat插件选择方法

    1. 进入Tomcat官网:http://tomcat.apache.org/ 选择Maven plugin 2. 选择版本 3. 查看版本对应的插件版本: 有两种方式添加:如下图所示:

  8. Leetcode 440.字典序第k小的数字

    字典序第k小的数字 给定整数 n 和 k,找到 1 到 n 中字典序第 k 小的数字. 注意:1 ≤ k ≤ n ≤ 109. 示例 : 输入: n: 13 k: 2 输出: 10 解释: 字典序的排 ...

  9. Python IO多路复用select模块

    多路复用的分析实例:服务端.客户端 #服务端配置 from socket import * import time import select server = socket(AF_INET, SOC ...

  10. Python socket粘包问题(初级解决办法)

    server端配置: import socket,subprocess,struct from socket import * server=socket(AF_INET,SOCK_STREAM) s ...