HDU 1698 Just a Hook 线段树区间更新、
来谈谈自己对延迟标记(lazy标记)的理解吧、
lazy标记的主要作用是尽可能的降低时间复杂度、
这样说吧、 如果你不用lazy标记,那么你对于一个区间更新的话是要对其所有的子区间都更新一次,但如果用lazy标记的话、 就只需要更新这一个区间然后加一个标记,那么如果要访问这个区间的子区间,因为有lazy标记,所以下次访问会将区间的lazy标记传递给子区间,让后去更新子区间,这样我们不必在每次区间更新操作的时候更新该区间的全部子区间,等下次查询到这个区间的时候只需要传递lazy标记就可以了
但从时间复杂度上来讲,肯定是划算的,那么对于要访问我们开始更新区间的子区间又如何呢、 一样,我们有又需要更新的所要查找的子区间,然后加一个lazy标记,等下次更新的时候传递这个标记就好了、
另外两个push函数放的位置可谓是递归的精髓、
递归真的好神奇、
- - 初学者、 言语方面可能表达不严谨
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int maxn=111111; 5 int h,w,n; 6 int col[maxn<<2]; 7 int sum[maxn<<2]; 8 void pushup(int rt) 9 { 10 sum[rt]=sum[rt<<1]+sum[rt<<1|1]; 11 } 12 void pushdown(int rt,int m) 13 { 14 if(col[rt]){ //传递标记并更新区间 15 col[rt<<1]=col[rt<<1|1]=col[rt]; 16 sum[rt<<1]=(m-(m>>1))*col[rt]; 17 sum[rt<<1|1]=(m>>1)*col[rt]; 18 col[rt]=0; 19 } 20 } 21 void build(int l,int r,int rt) 22 { 23 col[rt]=0; 24 sum[rt]=1; 25 if(l==r) return; 26 int m=(l+r)>>1; 27 build(l,m,rt<<1); 28 build(m+1,r,rt<<1|1); 29 pushup(rt); //递归尿性向上更新、 30 } 31 void updata(int L,int R,int c,int l,int r,int rt) 32 { 33 if(L<=l && r<=R){ 34 col[rt]=c; 35 sum[rt]=c*(r-l+1); 36 return; 37 } 38 pushdown(rt,r-l+1); //传递标记、 不得不说这两个push函数放的位置真的很能体现递归的作用 39 int m=(l+r)>>1; 40 if(L<=m) updata(L,R,c,l,m,rt<<1); 41 if(R>m) updata(L,R,c,m+1,r,rt<<1|1); 42 pushup(rt); //利用递归的尿性向上更新区间和、 43 } 44 int main() 45 { 46 int t,n,m; 47 int p=1; 48 scanf("%d",&t); 49 while(t--){ 50 scanf("%d%d",&n,&m); 51 build(1,n,1); 52 while(m--){ 53 int a,b,c; 54 scanf("%d%d%d",&a,&b,&c); 55 updata(a,b,c,1,n,1); 56 } 57 printf("Case %d: The total value of the hook is %d.\n",p++,sum[1]); 58 } 59 return 0; 60 }