线段树初步

 

线段树模板1:https://www.luogu.org/problem/show?pid=3372

线段树模板2:https://www.luogu.org/problem/show?pid=3373

这些都比较基础,就是1或2个lazy标记的时候怎么处理?几乎不用考虑兼容性的问题。

现在这里有一道充分考验线段树lazy的兼容性问题的题目,涉及到4个lazy标记,怎么处理?

例子1:求线段树维护一个区间,支持如下操作:区间修改为同一个值(更改1),区间加一个数(更改2),区间和(运算1),区间最大值(运算2):

解析:首先,不考虑lazy标记的兼容性是不行的,需要注意的是区间修改和区间和,区间最大值是不兼容的,所以在lazy时需要特判!!!

还有需要注意的点非常多,需要注意,

//本程序经过oycy0306测试正确性保障++
uses math;
const maxn=;
inf=;
type rec=record
add,mk:longint;
end;
var n,m,i,opx,opr,opl,ch,ans:longint;
f,ff,a:array[..maxn]of longint;
s:array[..maxn]of rec;
procedure build(x,l,r:longint);
var m:longint;
begin
s[x].mk:=inf;
s[x].add:=;
if l=r then begin
ff[x]:=a[l];
f[x]:=a[l];
exit;
end;
m:=(l+r)>>;
build(*x,l,m);
build(*x+,m+,r);
f[x]:=f[*x]+f[*x+];
ff[x]:=max(ff[*x],ff[*x+]);
end;
procedure down(x,l,r,m,lson,rson:longint);
begin
if s[x].mk<>inf then begin //**
s[lson].mk:=s[x].mk;
s[rson].mk:=s[x].mk;
s[lson].add:=;
s[rson].add:=;
f[lson]:=opx*(m-l+);
f[rson]:=opx*(r-m);
ff[lson]:=opx;
ff[rson]:=opx;
s[x].mk:=inf;
s[x].add:=;
exit;
end;
s[lson].mk:=inf;
s[rson].mk:=inf;
s[lson].add:=s[lson].add+s[x].add;
s[rson].add:=s[rson].add+s[x].add;
f[lson]:=f[lson]+s[x].add*(m-l+);
f[rson]:=f[rson]+s[x].add*(r-m);
ff[lson]:=ff[lson]+s[x].add;
ff[rson]:=ff[lson]+s[x].add;
s[x].add:=;
s[x].mk:=inf; //**
end;
procedure calc(x,l,r:longint);
var m:longint;
begin
if (opl<=l)and(opr>=r) then begin
case ch of
:begin s[x].mk:=opx; s[x].add:=; f[x]:=opx*(r-l+); ff[x]:=opx; end;
:begin s[x].add:=s[x].add+opx; f[x]:=f[x]+opx*(r-l+); ff[x]:=ff[x]+opx; end;
:begin ans:=ans+f[x]; end; //f:sum
:begin ans:=max(ff[x],ans)end; //ff:mk
end;
exit;
end;
m:=(l+r)>>;
if (s[x].mk<>inf)or(s[x].add>)then down(x,l,r,m,*x,*x+);
if opl<=m then calc(*x,l,m);
if opr>m then calc(*x+,m+,r);
if (ch=)or(ch=) then begin
f[x]:=f[*x]+f[*x+];
ff[x]:=max(ff[*x],ff[*x+])
end;
end;
begin
writeln('input nodenum n=??'); readln(n);
writeln('input a num(n) sequence called a[]==??');
for i:= to n do read(a[i]);
write('the strat sequence a[]==');
for i:= to n do write(a[i],' ');writeln;
writeln('---------------------------');
writeln('start to build XD tree.');
writeln('---------------------------');
build(,,n);
writeln('---------------------------');
writeln('XD tree is already built.');
writeln('---------------------------');
writeln('input your instructions number!'); //build ok!
readln(m); writeln('OK.');
writeln('---------------------------');
writeln('1=modify');
writeln('2=ADD');
writeln('3=question sum');
writeln('4=max in the a[]');
writeln('a line a word.');
writeln('instruction+ +minl+ +maxr+ (+valuable)');
writeln('---------------------------');
for i:= to m do begin
writeln('instruction input ',i,' :');
read(ch,opl,opr);
if (ch=)or(ch=) then readln else readln(opx);
case ch of
,:begin writeln('instruction output ',i,':'); writeln('Nothing except the instruction is running over.');calc(,,n); end;
,:begin ans:=; calc(,,n); writeln('instruction output ',i,' :'); writeln(ans); end;
end;
end;
end.

 例子2:求线段树维护一个区间,支持如下操作:区间修改为同一个值(更改1),区间加一个数(更改2),区间乘一个数(更该3),区间和(运算1),区间最大值(运算2):、

对于例子一又多了一个区间乘法,所以就有5个lazy标记了...

所以这个down函数比较的长; 具体不解释了,就是在例子1上增加,看代码:

uses math;
const maxn=;
inf=;
type rec=record
add,mk,mp:longint;
end;
var n,m,i,opx,opr,opl,ch,ans:longint;
f,ff,a:array[..maxn]of longint;
s:array[..maxn]of rec;
procedure build(x,l,r:longint);
var m:longint;
begin
s[x].mk:=inf;
s[x].add:=;
s[x].mp:=;
if l=r then begin
ff[x]:=a[l];
f[x]:=a[l];
// s[x].mx:=a[l];
exit;
end;
m:=(l+r)>>;
build(*x,l,m);
build(*x+,m+,r);
f[x]:=f[*x]+f[*x+];
ff[x]:=max(ff[*x],ff[*x+]);
end;
procedure down(x,l,r,m,lson,rson:longint);
begin
if s[x].mk<>inf then begin //**
s[lson].mk:=s[x].mk;
s[rson].mk:=s[x].mk;
s[lson].add:=;
s[rson].add:=;
s[lson].mp:=;
s[rson].mp:=;
f[lson]:=opx*(m-l+);
f[rson]:=opx*(r-m);
ff[lson]:=opx;
ff[rson]:=opx;
s[x].mk:=inf;
s[x].add:=;
s[x].mp:=;
exit;
end;
s[lson].mp:=s[lson].mp*s[x].mp;
s[rson].mp:=s[rson].mp*s[x].mp;
s[lson].add:=s[lson].add*s[x].mp;
s[rson].add:=s[rson].add*s[x].mp;
f[lson]:=f[lson]*s[x].mp;
f[rson]:=f[rson]*s[x].mp;
ff[lson]:=ff[lson]*s[x].mp;
ff[rson]:=ff[lson]*s[x].mp;
s[x].mp:=;
s[lson].mk:=inf;
s[rson].mk:=inf;
s[lson].add:=s[lson].add+s[x].add;
s[rson].add:=s[rson].add+s[x].add;
f[lson]:=f[lson]+s[x].add*(m-l+);
f[rson]:=f[rson]+s[x].add*(r-m);
ff[lson]:=ff[lson]+s[x].add;
ff[rson]:=ff[lson]+s[x].add;
s[x].add:=;
s[x].mk:=inf; //**
end;
procedure calc(x,l,r:longint);
var m:longint;
begin
if (opl<=l)and(opr>=r) then begin
case ch of
:begin s[x].mk:=opx; s[x].add:=; f[x]:=opx*(r-l+); ff[x]:=opx; end;
:begin s[x].add:=s[x].add+opx; f[x]:=f[x]+opx*(r-l+); ff[x]:=ff[x]+opx; end;
:begin ans:=ans+f[x]; end; //f:sum
:begin ans:=max(ff[x],ans)end; //ff:mk
:begin s[x].mp:=s[x].mp*opx; s[x].add:=s[x].add*opx; f[x]:=f[x]*opx; ff[x]:=ff[x]*opx; end;
end;
exit;
end;
m:=(l+r)>>;
if (s[x].mk<>inf)or(s[x].add>)or(s[x].mp<>)then down(x,l,r,m,*x,*x+);
if opl<=m then calc(*x,l,m);
if opr>m then calc(*x+,m+,r);
if (ch=)or(ch=) then begin
f[x]:=f[*x]+f[*x+];
ff[x]:=max(ff[*x],ff[*x+])
end;
end;
begin
writeln('input nodenum n=??'); readln(n);
writeln('input a num(n) sequence called a[]==??');
for i:= to n do read(a[i]);
write('the strat sequence a[]==');
for i:= to n do write(a[i],' ');writeln;
writeln('---------------------------');
writeln('start to build XD tree.');
writeln('---------------------------');
build(,,n);
writeln('---------------------------');
writeln('XD tree is already built.');
writeln('---------------------------');
writeln('input your instructions number!'); //build ok!
readln(m); writeln('OK.');
writeln('---------------------------');
writeln('1=modify');
writeln('2=ADD');
writeln('3=question sum');
writeln('4=max in the a[]');
writeln('5=multiplication');
writeln('a line a word.');
writeln('instruction+ +minl+ +maxr+ (+valuable)');
writeln('---------------------------');
for i:= to m do begin
writeln('instruction input ',i,' :');
read(ch,opl,opr);
if (ch=)or(ch=) then readln else readln(opx);
case ch of
,,:begin calc(,,n); writeln('instruction output ',i,':'); writeln('Nothing except the instruction is running over.'); end;
,:begin ans:=; calc(,,n); writeln('instruction output ',i,' :'); writeln(ans); end;
end;
end;
end.
 
 

线段树初步——转载自ljc20020730的更多相关文章

  1. 线段树初步&&lazy标记

    线段树 一.概述: 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a, ...

  2. 线段树初步__ZERO__.

    线段树,顾名思义,就是指一个个线段组成的树. 线段树的定义就是: 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点.使用线段树可以快速的查找某 ...

  3. 线段树总结 (转载 里面有扫描线类 还有NotOnlySuccess线段树大神的地址)

    转载自:http://blog.csdn.net/shiqi_614/article/details/8228102 之前做了些线段树相关的题目,开学一段时间后,想着把它整理下,完成了大牛NotOnl ...

  4. [转载]完全版线段树 by notonlysuccess大牛

    原文出处:http://www.notonlysuccess.com/ (好像现在这个博客已经挂掉了,在网上找到的全部都是转载) 今天在清北学堂听课,听到了一些很令人吃惊的消息.至于这消息具体是啥,等 ...

  5. 线段树详解 (原理,实现与应用)(转载自:http://blog.csdn.net/zearot/article/details/48299459)

    原文地址:http://blog.csdn.net/zearot/article/details/48299459(如有侵权,请联系博主,立即删除.) 线段树详解    By 岩之痕 目录: 一:综述 ...

  6. 一步一步理解线段树——转载自JustDoIT

    一步一步理解线段树   目录 一.概述 二.从一个例子理解线段树 创建线段树 线段树区间查询 单节点更新 区间更新 三.线段树实战 -------------------------- 一 概述 线段 ...

  7. 【转载】完全版线段树 by notonlysuccess大牛

    原文出处:http://www.notonlysuccess.com/ 今晚上比赛就考到了 排兵布阵啊,难受. [完全版]线段树 很早前写的那篇线段树专辑至今一直是本博客阅读点击量最大的一片文章,当时 ...

  8. Tido c++线段树知识讲解(转载)

    线段树知识讲解 定义.建树.单点修改.区间查询         特别声明:如上的讲解说的是区间最大值 如果想要查询区间和 只需要改变一下建树和查询的代码就行了,如下 其他根据自己的需要进行修改即可

  9. 线段树离散化 unique + 二分查找 模板 (转载)

    离散化,把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率. 通俗的说,离散化是在不改变数据相对大小的条件下,对数据进行相应的缩小.例如: 原数据:1,999,100000,15:处理 ...

随机推荐

  1. 服务端相关知识学习(三)Zookeeper的配置

    前面两篇文章介绍了Zookeeper是什么和可以干什么,那么接下来我们就实际的接触一下Zookeeper这个东西,看看具体如何使用,有个大体的感受,后面再描述某些地方的时候也能在大脑中有具体的印象.本 ...

  2. JXOI 2018滚粗记

    --Update5.2 成绩出了,见后文 听说省选VAN写游记是传统,本蒟蒻也来发一篇吧. DAY 0 本来以为省选不在JKFZ举行的结果又是在JKFZ,本校作战感觉终究会是好一些吧,和jyh一起向教 ...

  3. OSCP-Kioptrix2014-3 后渗透测试

    拿到root权限 之前的努力,最终获得了两个session 尝试看看该操作系统的漏洞 kali: searchsploit freebsd 9.0 cp /usr/share/exploitdb/ex ...

  4. zookeeper配置文件说明

    zoo.cfg #zoo.cfg 的内容 # 心跳检查的时间 2秒 tickTime=2000 # 初始化时 连接到服务器端的间隔次数,总时间10*2=20秒 initLimit=10 # ZK Le ...

  5. mysql调优——数据包大小限制max_allowed_packet

     mysql根据配置文件会限制server接受的数据包大小. 有时候大的插入和更新会受max_allowed_packet 参数限制,导致写入或者更新失败. 查看目前配置 show VARIABLES ...

  6. 在不同的Linux发行版上安装TFTP Server

    http://www.davidsudjiman.info/2006/03/27/installing-and-setting-tftpd-in-ubuntu/ http://www.cybercit ...

  7. 9、nginx常用基础模块

    1Nginx目录索引 ngx_http_autoindex_module模块处理以斜杠字符('/')结尾的请求(就是处理location /),并生成目录列表.当ngx_http_index_modu ...

  8. C++堆排序算法的实现

    堆排序(Heap sort)是指利用堆这种数据结构所设计的一种排序算法.堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点.堆排序可以用到上一次的 ...

  9. Linux系统组成和获取命令帮助4

    Linux文件系统:        1.文件名名称严格区分字符大小写        2.文件可以使用除/以外任意字符        3.文件名长度不能超过255字符        4.以.开头的文件为 ...

  10. zencart设置特价商品价格

    登录后台-工具-安装SQL脚本(Install SQL Patches) 运行以下语句: , '0001-01-01'); 红色部分请替换成实际要设置的数据:1234表示产品ID,888表示特价.