题面

Description

这是一道非常直白的可持久化线段树的练习题,目的并不是虐人,而是指导你入门可持久化数据结构。

线段树有个非常经典的应用是处理RMQ问题,即区间最大/最小值询问问题。现在我们把这个问题可持久化一下:

Q k l r 查询数列在第k个版本时,区间[l, r]上的最大值

M k p v 把数列在第k个版本时的第p个数修改为v,并产生一个新的数列版本

最开始会给你一个数列,作为第1个版本。

每次M操作会导致产生一个新的版本。修改操作可能会很多呢,如果每次都记录一个新的数列,空间和时间上都是令人无法承受的。所以我们需要可持久化数据结构:

对于最开始的版本1,我们直接建立一颗线段树,维护区间最大值。

修改操作呢?我们发现,修改只会涉及从线段树树根到目标点上一条树链上logn个节点而已,其余的节点并不会受到影响。所以对于每次修改操作,我们可以只重建修改涉及的节点即可。就像这样:

P

需要查询第k个版本的最大值,那就从第k个版本的树根开始,像查询普通的线段树一样查询即可。

Input

第一行两个整数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,并产生一个新的数列版本

Output

对于每个M询问,输出正确答案

Sample Input

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

Sample Output

4

5

4

4

Hint

样例解释:

序列版本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

Source

原题见: http://syzoj.com/problem/247

可持久化线段树

题解

主席树板子题

自己YY了一晚上弄出来了

到时候再写主席树的东西吧。。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define MAX 1000000
#define ll long long
inline int read()
{
register int x=0,t=1;
register char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-'){t=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
return x*t;
}
struct Node//线段树节点
{
int ch[2];//左儿子和右儿子
int l,r;//左节点右节点
int val;//最大值
}c[MAX];
int n,Q,a[MAX],cnt,Root[MAX];
void Build(int now,int l,int r)//构建第一版本的线段树
{
++cnt;
c[now].l=l;c[now].r=r;
if(l==r){c[now].val=a[l];return;}
int mid=(l+r)>>1;
c[now].ch[0]=cnt+1;
Build(cnt+1,l,mid);
c[now].ch[1]=cnt+1;
Build(cnt+1,mid+1,r);
c[now].val=max(c[c[now].ch[0]].val,c[c[now].ch[1]].val);
}
int Query(int now,int al,int ar)//查询最大值
{
int l=c[now].l,r=c[now].r;
if(l==al&&ar==r)return c[now].val;
int lson=c[now].ch[0],rson=c[now].ch[1];
int mid=(l+r)>>1;
if(ar<=mid)return Query(lson,al,ar);
if(al>mid)return Query(rson,al,ar);
return max(Query(lson,al,mid),Query(rson,mid+1,ar));
}
void Update(int now,int k,int x)
{
++cnt;int tt=cnt;
c[cnt]=c[now];//直接复制要更新的节点
int l=c[now].l,r=c[now].r;
if(l==r){c[cnt].val=x;return;}
int mid=(l+r)>>1;
if(k<=mid){c[tt].ch[0]=cnt+1;Update(c[now].ch[0],k,x);}
else{c[tt].ch[1]=cnt+1;Update(c[now].ch[1],k,x);}
c[tt].val=max(c[c[tt].ch[0]].val,c[c[tt].ch[1]].val);
}
int main()
{
n=read();Q=read();
for(int i=1;i<=n;++i)a[i]=read();
Build(1,1,n);Root[1]=1;
int Ver=1;
while(Q--)
{
int tt=read(),k=read(),L=read(),R=read();
if(tt==0)
printf("%d\n",Query(Root[k],L,R));
else
{
Root[++Ver]=cnt+1;//当前新版本的根节点
Update(Root[k],L,R);
}
}
}

【CJOJ2316】【模板】可持久化线段树的更多相关文章

  1. 【洛谷P3834】(模板)可持久化线段树 1(主席树)

    [模板]可持久化线段树 1(主席树) https://www.luogu.org/problemnew/show/P3834 主席树支持历史查询,空间复杂度为O(nlogn),需要动态开点 本题用一个 ...

  2. 洛谷P3834 [模板]可持久化线段树1(主席树) [主席树]

    题目传送门 可持久化线段树1(主席树) 题目背景 这是个非常经典的主席树入门题——静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个正整数构成的序列,将对于指定 ...

  3. 洛谷.3834.[模板]可持久化线段树(主席树 静态区间第k小)

    题目链接 //离散化后范围1~cnt不要错 #include<cstdio> #include<cctype> #include<algorithm> //#def ...

  4. [学习笔记] 可持久化线段树&主席树

    众所周知,线段树是一个非常好用也好写的数据结构, 因此,我们今天的前置技能:线段树. 然而,可持久化到底是什么东西? 别急,我们一步一步来... step 1 首先,一道简化的模型: 给定一个长度为\ ...

  5. Luogu P3919 【模板】可持久化数组 可持久化线段树

    其实就是可持久化线段树的模板题线段树不会看这里 #include<bits/stdc++.h> ; using namespace std; ]; ],rc[N*],val[N*],cnt ...

  6. LuoguP3834 【模板】可持久化线段树 1(主席树)|| 离散化

    题目:[模板]可持久化线段树 1(主席树) 不知道说啥. #include<cstdio> #include<cstring> #include<iostream> ...

  7. Luogu P3919【模板】可持久化数组(可持久化线段树/平衡树)

    题面:[模板]可持久化数组(可持久化线段树/平衡树) 不知道说啥,总之我挺喜欢自己打的板子的! #include<cstdio> #include<cstring> #incl ...

  8. 洛谷 P3919 【模板】可持久化数组(可持久化线段树/平衡树)-可持久化线段树(单点更新,单点查询)

    P3919 [模板]可持久化数组(可持久化线段树/平衡树) 题目背景 UPDATE : 最后一个点时间空间已经放大 标题即题意 有了可持久化数组,便可以实现很多衍生的可持久化功能(例如:可持久化并查集 ...

  9. 洛谷——P3919 【模板】可持久化数组(可持久化线段树/平衡树)

    P3919 [模板]可持久化数组(可持久化线段树/平衡树) 题目背景 UPDATE : 最后一个点时间空间已经放大 标题即题意 有了可持久化数组,便可以实现很多衍生的可持久化功能(例如:可持久化并查集 ...

随机推荐

  1. js小技巧:数组去重

    JavaScript 数组中去除重复的数据 var arr = [1, 2, 2, 3, '1', null, 'a', 'b', 'a']; var t = {}; var result = arr ...

  2. 前端js代码优化

    今天给大家分享下js代码优化的相关技巧. 1.使用"+"转换为数值     我们平时开发过程中需要将数字字符串创转为number类型,大多数都会用JavaScript parseI ...

  3. selenium2 python自动化测试实战(回归测试)

    selenium2 python自动化测试实战 最近接手商城的项目,针对后台测试,功能比较简单,但是流程比较繁多,涉及到前后台的交叉测试.在对整个项目进行第一轮测试完成之后,考虑以后回归测试任务比较重 ...

  4. Vi/Vim的快捷方式

    1 vi/ vim键盘图 2 文字解说 进入编辑模式的6种方式: i在光标前插入 I在行首插入 a在光标后插入 A在行末插入 o在下一行插入 O在上一行插入 删除字符 x 删除当前字符 X 删除前一个 ...

  5. [ZJOI2008]骑士

    [ZJOI2008]骑士 标签: DP 题目链接 题解 把边看成无向的. 其实就是求这个东西的最大独立集. 但是这不是树,怎么求呢? 其实还是一样的求法. 对于每一个连通块.最多有这个联通块的大小数目 ...

  6. java基础--面对对象

    面对对象--概述 什么是对象? +---->对象可以泛指一切现实中存着的事物 +---->类是对象的抽象集合 什么是面对对象? +--->万物皆对象,面对对象实际就是人与万物接触== ...

  7. Android ADB Server启动失败

    启动Android Stdio的时候报如下错误: Unable to create Debug Bridge: Unable to start adb server: error: could not ...

  8. HDU - 3533 bfs [kuangbin带你飞]专题二

    看了好久的样例才看懂. 题意:有一个人要从(0,0)走到(n,m),图中有k个碉堡,每个碉堡可以向某个固定的方向每隔t秒放一次炮,炮弹不能穿越另一个碉堡,会被阻挡.人在移动的过程中不会被炮弹打到,也就 ...

  9. APICloud常用模块

    常用模块 基础 fs db 支付 wxPay aliPay unionPay 消息 ajpush rongCloud2

  10. linux mysql重启命令

    1.通过rpm包安装的MySQL 1 2 service mysqld restart /etc/inint.d/mysqld start 2.从源码包安装的MySQL 1 2 3 4 // Linu ...