线段树lazytag优化模板
线段树嘛。。。很基本的一种数据结构啦
lazytag优化能不错的提高效率
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
我的代码风格可能有点丑,请各位看官别介意
具体可以参见这里
下面简单来介绍下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的精髓,然后即可套用模板,本模板实现了更新、查询操作。
这篇文章由TonyFang发布。
所有解释权归TonyFang所有。
Mailto: tony-fang@map-le.net