题面

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. Python面向对象篇(2)-继承

    在发表本篇随笔的时候,距离上一次发已经有一个多月了,很多朋友私信我为什么不持续更新了,在这里先跟大家说声抱歉.因为年底的工作较为繁重,实在分不出精力,更重要的也是在思考后面进阶的部分要按怎样的顺序写, ...

  2. weblogic修改jdk版本遇到的问题与解决方法

    1.修改setDomainEnv ,路径.../domains/xx_domain\bin\ 1.1修改JAVA_HOME为需要修改的路径 注意:BEA_JAVA_HOME路径不需修改 2.修改路径后 ...

  3. Sql server 卸载方法

    sql server不正确卸载时,重新安装会失败,会提示各种错误:如数据库实例已存在等... 下面是我摸索总结出来的卸载方法,以及重装失败后的处理方法: 卸载方法: 注意:SQL Server 200 ...

  4. JavaScript 知识点

    JS基础 页面由三部分组成: html:超文本标记语言,负责页面结构 css:层叠样式表,负责页面样式 js:轻量级的脚本语言,负责页面的动效和数据交互 小总结:结构,样式和行为,三者相分离 在htm ...

  5. Oracle批量操作数据库

    1:批量插入 <insert id="insertBatch" parameterType="Java.util.List" > insert in ...

  6. Python个人总结_02

    个人学习总结: python 第二课 解释型和编译型语言 计算机是不能够识别高级语言的,当我们运行一个高级语言的时候,需要将高级语言 翻译成计算机能够读懂的机器语言.这个过程分为两类,一个是编译,一个 ...

  7. ubuntu下boost编译安装

    ubuntu下boost编译安装 boost 安装 1.依赖安装 apt-get install mpi-default-dev libicu-dev python-dev python3-dev l ...

  8. centos/linux下的安装mysql

    1.从yum 下面下载mysql数据库 yum -y install mysql-server 2.查询该mysql是否安装完成 rpm -qa|grep mysql-server 出现如下图所示标明 ...

  9. java复习笔记

    本笔记(无异常处理与网络编程部分)整理自<java程序设计>-黄岚 王岩 王康平 编著 java数据     UI     I/O      java线程      数据库操作 Java数 ...

  10. JDBC数据库操作

    JDBC:   创建SQL语句对象    Statement statement = (Statement) con.createStatement() ;   调用执行     statement. ...