关于使用lazytag的线段树两种查询方式的比较研究
说到线段树,想来大家并不陌生——最基本的思路就是将其规划成块,然后只要每次修改时维护一下即可。
但是尤其是涉及到区间修改时,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的线段树两种查询方式的比较研究的更多相关文章
- ZOJ-1610 线段树+两种查询方法(弥补我线段树区间填充的短板)
ZOJ-1610 线段树+两种查询方法(弥补我线段树区间填充的短板) 题意 题意:给一个n,代表n次操作,接下来每次操作表示把[l,r]区间的线段涂成k的颜色其中,l,r,k的范围都是0到8000 这 ...
- codevs 2216 线段树 两种更新方式的冲突
题目描述 Description “神州“载人飞船的发射成功让小可可非常激动,他立志长大后要成为一名宇航员假期一始,他就报名参加了“小小宇航员夏令营”,在这里小可可不仅学到了丰富的宇航知识,还参与解决 ...
- easyui datagride 两种查询方式
easyui datagride 两种查询方式function doReseach() { //$('#tt').datagrid('load', { // FixedCompany: $('.c_s ...
- HashMap两种遍历方式的深入研究
转自:http://swiftlet.net/archives/1259 HashMap的遍历有两种方式,如下所示:第一种利用entrySet的方式: 1 2 3 4 5 6 7 Map map ...
- js的两种查询方式 LHS and RHS
为了进一步理解,我们需要多介绍一点编译器的术语.编译器在编译过程的第二步中生成了代码,引擎执行它时,会通过查找变量 a 来判断它是否已声明过.查找的过程由作用域进行协助,但是引擎执行怎样的查找,会影响 ...
- mysql查询字段类型为json时的两种查询方式。
表结构如下: id varchar(32) info json 数据: id = info = {"age": "18","di ...
- POJ 3225 线段树区间更新(两种更新方式)
http://blog.csdn.net/niuox/article/details/9664487 这道题明显是线段树,根据题意可以知道: (用0和1表示是否包含区间,-1表示该区间内既有包含又有不 ...
- POJ 2299-Ultra-QuickSort-线段树的两种建树方式
此题有两种建树方式! Description In this problem, you have to analyze a particular sorting algorithm. The algo ...
- 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序加上一个线 ...
随机推荐
- SpringMVC+RestFul详细示例实战教程
一.SpringMVC基础入门,创建一个HelloWorld程序 1.首先,导入SpringMVC需要的jar包. 2.添加Web.xml配置文件中关于SpringMVC的配置 <!--conf ...
- Unable to find setter method for attribute: 属性名
tld文件里面的名称和标签内的属性名要一致.
- 【js编程艺术】小制作五
1.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <ti ...
- 《JAVASCRIPT高级程序设计》第二章
把javascript应用在网页中,需要涉及web的核心语言-html:如何让javascript既能与html共存,又不影响页面的显示效果,经过长时间的讨论.试错,最终的决定是为web增加统一的脚本 ...
- [CSS3] 学习笔记-CSS3选择器详解(一)
1.属性选择器 在CSS3中,追加了3个属性选择器,分别为:[att*=val].[att^=val]和[att$=val],使得属性选择器有了通配符的概念. <!doctype html> ...
- intelliJ IDEA创建web工程
1.创建project,也就是eclipse里的workspace,eclipse里1个工作空间里可以创建多个工程,idea的一个工作空间里只创建1个工程. File -- New -- Projec ...
- GIS制图课程目录(持续整理)
GIS制图课程目录 by 李远祥 由于过去一年都没有进行更新,近期终于抽出时间来进行相关知识的整理,因此,对专项技术进行了不同技术线条的梳理.为了方便阅读,特意整理一下全书的目录结构,希望对读者有帮助 ...
- Myeclipese改变背景色
https://www.baidu.com/s?wd=Myeclipese%E6%94%B9%E5%8F%98%E8%83%8C%E6%99%AF%E8%89%B2&ie=utf-8& ...
- 报表学习总结(一)——ASP.NET 水晶报表(Crystal Reports)的简单使用
一.水晶报表简介 Crystal Reports(水晶报表)是一款商务智能(BI)软件,主要用于设计及产生报表.水晶报表是业内最专业.功能最强的报表系统,它除了强大的报表功能外.最大的优势是实现了与绝 ...
- C语言 二维数组复制、清零及打印显示
#include <stdlib.h> #include <stdio.h> #include <string.h> //二维整型数组打印显示 ],int row, ...