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. 每天一个linux命令(13):less命令

    less 工具也是对文件或其它输出进行分页显示的工具,应该说是linux正统查看文件内容的工具,功能极其强大.less 的用法比起 more 更加的有弹性.在 more 的时候,我们并没有办法向前面翻 ...

  2. 201621123080《Java程序设计》第十一周学习总结

    201621123080<Java程序设计>第十一周学习总结 1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 2. 书面作业 本次PTA作业题集多线程 ...

  3. 使用kickstart + pxe 部署无人值守安装

    1.作为中小公司的运维,经常会遇到一些机械式的重复工作,例如:有时公司同时上线几十甚至上百台服务器,而且需要我们在短时间内完成系统安装. 常规的安装系统方法: 光盘安装系统:一个服务器DVD内置光驱百 ...

  4. Golang map并发 读写锁

    golang并发 一:只有写操作 var ( count int l = sync.Mutex{} m = make(map[int]int) ) //全局变量并发写 导致计数错误 func vari ...

  5. python标准输入输出

    input() 读取键盘输入 input() 函数从标准输入读入一行文本,默认的标准输入是键盘. input 可以接收一个Python表达式作为输入,并将运算结果返回. print()和format( ...

  6. python模块之datetime

    相比于time模块,datetime模块的接口则更直观.更容易调用 datetime模块定义了下面这几个类: datetime.date:表示日期的类.常用的属性有year, month, day: ...

  7. linux系统装载ELF过程

    参考:程序员的自我修养 fork -->execve() //----kenerl space--------------- sys_execve() /*arch\i386\kernel\pr ...

  8. FSMC原理通俗解释

    所以不用GPIO口直接驱动液晶,是因为这种方法速度太慢,而FSMC是用来外接各种存储芯片的,所以其数据通信速度是比普通GPIO口要快得多的.TFT-LCD 驱动芯片的读写时序和SRAM的差不多,所以就 ...

  9. 设置eclipse中的${user}

    打开eclipse根目录找到eclipse.ini文件增加初始配置: -Duser.name=snzigod@hotmail.com 重启eclipse后${user}变量的值就变成了snzigod@ ...

  10. C#发送邮件异常,返回信息乱码

    发邮件时出现了异常: 在 System.Net.Mail.MailCommand.CheckResponse(SmtpStatusCode statusCode, String response) 在 ...