码迷,mamicode.com
首页 > 其他好文 > 详细

线段树lazytag优化模板

时间:2015-05-20 23:42:33      阅读:142      评论:0      收藏:0      [点我收藏+]

标签:

线段树嘛。。。很基本的一种数据结构啦

lazytag优化能不错的提高效率

技术分享
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int MAX=1000000;
 4 struct pr {
 5     int sum;
 6     int lazy;
 7     int left,right;
 8 }tr[MAX+10];
 9 int n;
10 inline int ll(int k) {return 2*k;}
11 inline int rr(int k) {return 2*k+1;}
12 inline int mid(int kk1,int kk2) {return (kk1+kk2)>>1;}
13 void pushdown(int k) {
14     if (tr[k].lazy) {
15         tr[ll(k)].sum=tr[k].lazy*(tr[ll(k)].right-tr[ll(k)].left+1);
16         tr[rr(k)].sum=tr[k].lazy*(tr[rr(k)].right-tr[rr(k)].left+1);
17         tr[ll(k)].lazy=tr[rr(k)].lazy=tr[k].lazy;
18         tr[k].lazy=0;
19     }
20 }
21 
22 void build(int k,int s,int t) {
23     tr[k].left=s;tr[k].right=t;
24     if(s==t) {tr[k].sum=1;return;}
25     build(ll(k),s,mid(s,t));
26     build(rr(k),mid(s,t)+1,t);
27     tr[k].sum=tr[ll(k)].sum+tr[rr(k)].sum;
28 }
29 
30 void modify(int k,int s,int t,int x) {
31     int l=tr[k].left,r=tr[k].right;
32     if(t<l||r<s) {
33         tr[k].lazy=x;
34         tr[k].sum=x*(r-l+1);
35         return ;
36     }
37     pushdown(k);
38     int mi=mid(l,r);
39     if(t<=mi) modify(ll(k),s,t,x);
40     else if(s>mi) modify(rr(k),s,t,x);
41     else {
42         modify(ll(k),s,mi,x);
43         modify(rr(k),mi+1,t,x);
44     }
45     tr[k].sum=tr[ll(k)].sum+tr[rr(k)].sum;
46 }
47 int query(int k,int s,int t) {
48     int l=tr[k].left,r=tr[k].right;
49     if(l==s&&r==t) return tr[k].sum;
50     pushdown(k);
51     int mi=mid(l,r);
52     int res=0;
53     if (t<=mi) res+=query(ll(k),s,t);
54     else if(s>mi) res+=query(rr(k),s,t);
55     else res+=query(ll(k),s,mi)+query(rr(k),mi+1,t);
56     return res;
57 }
View Code

我的代码风格可能有点丑,请各位看官别介意

具体可以参见这里

下面简单来介绍下Lazytag思想:

什么是LazyTag?线段树要修改很多次,但是很多次修改的值并没有被用到,这几次修改就是无用的,那么我们通过加一个lazy变量,记录当前需要往下传递的数值,待有用时再继续往下传递,这就是LazyTag思想。向下传递可见我的代码pushdown();

介绍Lazy思想:lazy-tag思想,记录每一个线段树节点的变化值,当这部分线段的一致性被破坏我们就将这个变化值传递给子区间,大大增加了线段树的效率。

——yicbs

在此通俗的解释我理解的Lazy意思,比如现在需要对[a,b]区间值进行加c操作,那么就从根节点[1,n]开始调用update函数进行操作,如果刚好执行到一个子节点,它的节点标记为rt,这时tree[rt].l == a && tree[rt].r == b 这时我们可以一步更新此时rt节点的sum[rt]的值,sum[rt] += c * (tree[rt].r - tree[rt].l + 1),注意关键的时刻来了,如果此时按照常规的线段树的update操作,这时候还应该更新rt子节点的sum[]值,而Lazy思想恰恰是暂时不更新rt子节点的sum[]值,到此就return,直到下次需要用到rt子节点的值的时候才去更新,这样避免许多可能无用的操作,从而节省时间 。

——yicbs

读者只要理解了这几句话,就理解了lazytag的精髓,然后即可套用模板,本模板实现了更新、查询操作。

线段树lazytag优化模板

标签:

原文地址:http://www.cnblogs.com/TonyNeal/p/segmenttree.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!