说到线段树,想来大家并不陌生——最基本的思路就是将其规划成块,然后只要每次修改时维护一下即可。

但是尤其是涉及到区间修改时,lazytag的使用往往能够对于程序的质量起到决定性作用(Ex:一般JSOI2008左右的线段树题目,如果有区间修改的话,那么假如普普通通的一个个修改的话,那么一般30分左右,甚至更少;而有了神奇的lazytag,只要别的地方写的还算基本到位,一般就Accept了)

lazytag的基本思想也就是在需要修改的区间打上标记,然后下次动态维护标记和真正值之间的关系,然后查询或者下一个修改操作涉及此区间时,进行进一步维护。

于是,此时就存在两种不同的查询操作了(此处以BZOJ1798为例)

方案一:当查询过程中,遇到了带有标记的点,则将其记录下来(即并入综合的修改参数里面),然后当刚好找到合适区间是,再操作之

 function cal(z,x,y,l,r:longint;d:vet):int64;inline;
var d1:vet;
begin
if l>r then exit();
d1:=merge(b[z],d);
if (x=l) and (y=r) then exit(((a[z]*d1.a0) mod p+(d1.a1*((r-l+) mod p)) mod p) mod p);
exit((cal(z*,x,(x+y) div ,l,min((x+y) div ,r),d1)+cal(z*+,(x+y) div +,y,max((x+y) div +,l),r,d1)) mod p);
end;

这个方案在操作时,实际上并没有动任何的标记,直接通过现有的标记求出了值

方案二:查询过程中遇到标记点的话,则将其扩展下去,保证一路下来都不存在标记点,然后到地方了之后直接返回数值

 function cal(z,x,y,l,r:longint):int64;inline;
begin
if l>r then exit();
ext(z,x,y);
if (x=l) and (y=r) then exit(a[z]);
exit((cal(z*,x,(x+y) div ,l,min((x+y) div ,r))+cal(z*+,(x+y) div +,y,max((x+y) div +,l),r)) mod p);
end;

附:ext操作和merge操作

 function merge(d1,d2:vet):vet;inline;
var d3:vet;
begin
d3:=d1;
d3.a0:=d3.a0 mod p;d3.a1:=d3.a1 mod p;
d2.a0:=d2.a0 mod p;d2.a1:=d2.a1 mod p;
d3.a0:=(d3.a0*d2.a0) mod p;
d3.a1:=((d3.a1*d2.a0) mod p+d2.a1) mod p;
exit(d3);
end;
procedure ext(z,x,y:longint);inline;
begin
a[z]:=((a[z]*b[z].a0) mod p+(b[z].a1*((y-x+) mod p)) mod p) mod p;
b[z*]:=merge(b[z*],b[z]);
b[z*+]:=merge(b[z*+],b[z]);
b[z].a0:=;b[z].a1:=;
end;

此方法比较直观,比较好想,但是看样子好多标记其实被操作了

好了,现在看下时间对比:(注:此两个程序中除了cal函数不一样其他均一样)

方案一:

方案二:(这个里面方案一的cal函数是通过{}注释掉的,所以代码会多出来那么些)

空间上差不多(phile:这不显然的么呵呵呵),时间上方案一要快,原因其实还是因为方案一并没有涉及到修改标记的操作,而方案二涉及了,而且尤其对于tag很密集的树,操作更是会较为复杂。还有方案二虽然更加直观易想,但是代码其实并没有缩减,两者代码复杂度几乎一样。所以综合而言,方案一更加划算么么哒

下面附上BZOJ1798代码

 /**************************************************************
Problem:
User: HansBug
Language: Pascal
Result: Accepted
Time: ms
Memory: kb
****************************************************************/ type
vet=record
a0,a1:int64;
end;
var
i,j,k,l,m,n,a2,a3,a4:longint;
p:int64;
a,c:array[..] of int64;
b:array[..] of vet;
d,d1:vet;
procedure built(z,x,y:longint);inline;
begin
if x=y then
a[z]:=c[x] mod p
else
begin
built(z*,x,(x+y) div );
built(z*+,(x+y) div +,y);
a[z]:=(a[z*]+a[z*+]) mod p;
end;
b[z].a0:=;b[z].a1:=;
end;
function max(x,y:longint):longint;inline;
begin
if x>y then max:=x else max:=y;
end;
function min(x,y:longint):longint;inline;
begin
if x<y then min:=x else min:=y;
end;
function merge(d1,d2:vet):vet;inline;
var d3:vet;
begin
d3:=d1;
d3.a0:=d3.a0 mod p;d3.a1:=d3.a1 mod p;
d2.a0:=d2.a0 mod p;d2.a1:=d2.a1 mod p;
d3.a0:=(d3.a0*d2.a0) mod p;
d3.a1:=((d3.a1*d2.a0) mod p+d2.a1) mod p;
exit(d3);
end;
procedure ext(z,x,y:longint);inline;
begin
a[z]:=((a[z]*b[z].a0) mod p+(b[z].a1*((y-x+) mod p)) mod p) mod p;
b[z*]:=merge(b[z*],b[z]);
b[z*+]:=merge(b[z*+],b[z]);
b[z].a0:=;b[z].a1:=;
end;
function op(z,x,y,l,r:longint;d:vet):int64;inline;
var
a3,a4:int64;
begin
if l>r then exit();
ext(z,x,y);
if (x=l) and (y=r) then
begin
b[z]:=d;
exit(((a[z]*((b[z].a0-) mod p)) mod p+(b[z].a1*((r-l+) mod p)) mod p) mod p);
end
else
begin
a3:=op(z*,x,(x+y) div ,l,min(r,(x+y) div ),d);
a4:=op(z*+,(x+y) div +,y,max(l,(x+y) div +),r,d);
a[z]:=(a[z]+(a3+a4) mod p) mod p;
exit((a3+a4) mod p);
end;
end;
{function cal(z,x,y,l,r:longint;d:vet):int64;inline; //方案一
var d1:vet;
begin
if l>r then exit(0);
d1:=merge(b[z],d);
if (x=l) and (y=r) then exit(((a[z]*d1.a0) mod p+(d1.a1*((r-l+1) mod p)) mod p) mod p);
exit((cal(z*2,x,(x+y) div 2,l,min((x+y) div 2,r),d1)+cal(z*2+1,(x+y) div 2+1,y,max((x+y) div 2+1,l),r,d1)) mod p);
end; }
function cal(z,x,y,l,r:longint):int64;inline; //方案二
begin
if l>r then exit();
ext(z,x,y);
if (x=l) and (y=r) then exit(a[z]);
exit((cal(z*,x,(x+y) div ,l,min((x+y) div ,r))+cal(z*+,(x+y) div +,y,max((x+y) div +,l),r)) mod p);
end; function modd(x:int64):int64;inline;
begin
if x>= then exit(x mod p);
modd:=((abs(x) div p+)*p+x) mod p;
end; begin
readln(n,p);
for i:= to n do read(c[i]);
readln;
built(,,n);
readln(m);
for i:= to m do
begin
read(j);
case j of
:begin
readln(a2,a3,a4);
d.a0:=a4;d.a1:=;
op(,,n,a2,a3,d);
end;
:begin
readln(a2,a3,a4);
d.a0:=;d.a1:=a4;
op(,,n,a2,a3,d);
end;
:begin
readln(a2,a3);
writeln(modd(cal(,,n,a2,a3)));
end;
end;
end;
end.

关于使用lazytag的线段树两种查询方式的比较研究的更多相关文章

  1. ZOJ-1610 线段树+两种查询方法(弥补我线段树区间填充的短板)

    ZOJ-1610 线段树+两种查询方法(弥补我线段树区间填充的短板) 题意 题意:给一个n,代表n次操作,接下来每次操作表示把[l,r]区间的线段涂成k的颜色其中,l,r,k的范围都是0到8000 这 ...

  2. codevs 2216 线段树 两种更新方式的冲突

    题目描述 Description “神州“载人飞船的发射成功让小可可非常激动,他立志长大后要成为一名宇航员假期一始,他就报名参加了“小小宇航员夏令营”,在这里小可可不仅学到了丰富的宇航知识,还参与解决 ...

  3. easyui datagride 两种查询方式

    easyui datagride 两种查询方式function doReseach() { //$('#tt').datagrid('load', { // FixedCompany: $('.c_s ...

  4. HashMap两种遍历方式的深入研究

    转自:http://swiftlet.net/archives/1259 HashMap的遍历有两种方式,如下所示:第一种利用entrySet的方式:   1 2 3 4 5 6 7 Map map ...

  5. js的两种查询方式 LHS and RHS

    为了进一步理解,我们需要多介绍一点编译器的术语.编译器在编译过程的第二步中生成了代码,引擎执行它时,会通过查找变量 a 来判断它是否已声明过.查找的过程由作用域进行协助,但是引擎执行怎样的查找,会影响 ...

  6. mysql查询字段类型为json时的两种查询方式。

    表结构如下: id        varchar(32) info     json 数据: id = info = {"age": "18","di ...

  7. POJ 3225 线段树区间更新(两种更新方式)

    http://blog.csdn.net/niuox/article/details/9664487 这道题明显是线段树,根据题意可以知道: (用0和1表示是否包含区间,-1表示该区间内既有包含又有不 ...

  8. POJ 2299-Ultra-QuickSort-线段树的两种建树方式

    此题有两种建树方式! Description In this problem, you have to analyze a particular sorting algorithm. The algo ...

  9. Codeforces Round #442 (Div. 2) E Danil and a Part-time Job (dfs序加上一个线段树区间修改查询)

    题意: 给出一个具有N个点的树,现在给出两种操作: 1.get x,表示询问以x作为根的子树中,1的个数. 2.pow x,表示将以x作为根的子树全部翻转(0变1,1变0). 思路:dfs序加上一个线 ...

随机推荐

  1. 数据库设计的误区—>CHAR与VARCHAR

    字符型字段是数据库表中最常见的字段,而字符型字段又分为定长和变长两种.一般来说,VARCHAR类型用于存储内容长度变化较大的数据,CHAR类型用于存储内容长度没有变化或变化不大的数据. 在数据的内部存 ...

  2. DNS没有生效的几个原因

    1.记录没有正确添加 请确认你的域名记录是否完全正确的添加.线路类型正确,记录类型正确 2.域名还没有生效 这个情况还会有另外一个现象,就是域名有时候可以ping,有时候不能ping. 这是因为你当地 ...

  3. bootstrap 按钮 文本 浮动 隐藏

    bootstrap 按钮 文本 浮动 隐藏 <!DOCTYPE html> <html lang="en"> <head> <meta c ...

  4. Microsoft Office 2016 简体中文 Vol 版镜像下载(Pro Plus、Visio、Project 下载)

    在使用上,零售版和批量授权版并没有区别,只是授权方式方面的区别,相对而言,VOL 版的更容易激活一些,其他并没有什么区别了. 有需要的可以在下面下载:(以下均是 VL 版) 版本:Office 201 ...

  5. Codeforces374A

    A. Inna and Pink Pony time limit per test1 second memory limit per test 256 megabytes input standard ...

  6. HDU1716(全排列)

    排列2 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...

  7. 20个常用的Java程序块

    1.字符串有整型的相互转换 String a = String.valueOf(2);//integer to numeric string Int i = Integer.parseInt(a);/ ...

  8. C++ Primer 笔记 第二章

    C++ Primer 第二章 变量和基本类型 2.1基本内置类型 有算数类型和void类型:算数类型储存空间大小依及其而定. 算数类型表: 类型 含义 最小储存空间 bool 布尔型 - char 字 ...

  9. C++编程练习(9)----“图的存储结构以及图的遍历“(邻接矩阵、深度优先遍历、广度优先遍历)

    图的存储结构 1)邻接矩阵 用两个数组来表示图,一个一维数组存储图中顶点信息,一个二维数组(邻接矩阵)存储图中边或弧的信息. 2)邻接表 3)十字链表 4)邻接多重表 5)边集数组 本文只用代码实现用 ...

  10. iOS开发一些小技巧

    1.隐藏多余的tableView的cell分割线 self.tableView.tableFooterView= [[UIViewalloc]init]; 2.取消系统自带的返回字样 [[UIBarB ...