HDU - 1698(区间修改,取件查询,lazy区间标记更新)

题意

给你个大区间,区间上初始值皆为1,然后给出一系列修改操作,查询操作。
修改操作可修改区间l~r上的值为k(1,2,3),查询操作问区间 l ~ r上的数值总和为多少。

解释

利用线段树,求和版本,但利用lazy标记,lazy只标记在符合更新的区间内的区间点。然后在query里写在向下更新前,进行pushdown的lazy更新。pushdown中利用lazy得到子节点的lazy值,同时为两个子区间节点的值赋值成(或加上)对应区间应得的值。
在update中对由于当前子区间在范围内,给lazy重新赋值,即使前面该lazy也被赋值过,但结果以后更新为准,这样就减少了更新,达成了lazy的作用。
在查询中,也是需要用到查询的区间,lazy才往下pushdown,尽量减少不必要的操作得到结果。

#include <cstdio>
int num[100001*4];
int lazy[100001*4];
void bulit(int l, int r,int ret){
	int m = (l+r)/2;
	lazy[ret] = 0;
	if(r == l){
		num[ret] = 1;
		return ;
	}
	bulit(l, m, ret*2);
	bulit(m+1, r, ret*2+1);
	num[ret] = num[ret*2] + num[ret*2+1];
}
void pushdown(int l, int r, int ret){
	if(lazy[ret]){
		lazy[ret*2] = lazy[ret*2+1] = lazy[ret];
		int m = (l+r)/2;
		num[ret*2] = (m-l+1)*lazy[ret]; 
		num[ret*2+1] = (r-(m+1)+1)*lazy[ret];
		lazy[ret] = 0;
	}
}
void change(int L, int R, int l, int r, int key, int ret){
	int m = (l+r)/2;
	if(L<= l&& r<= R){
		lazy[ret] = key;
		num[ret] = (r-l+1)*key;
		return ;
	}
	pushdown(l, r, ret);
	if(L<= m) change(L, R, l, m, key, ret*2);
	if(R> m) change(L, R, m+1, r, key, ret*2+1);
	num[ret] = num[ret*2] + num[ret*2+1];
}
int ans = 0;
int query(int L, int R, int l, int r, int ret){
	int ans = 0;
	int m = (l+r)/2;
	if(L <= l && r <= R){
        return num[ret];
    }
    pushdown(l, r, ret);
    ans = 0;
    m = (l+r)>>1;
    if(L <= m) ans += query(L, R, l, m, ret*2);
    if(R >= m+1) ans += query(L, R, m+1, r, ret*2+1); 
    return ans;
}
int main(){
	int t;
	int n, m;
	int r, l, v;
	scanf("%d", &t);
	int cont = 1;
	while(t--){	
		scanf("%d %d", &n,&m);
		bulit(1, n, 1);
		for(int i = 0; i < m; i++)
		{
			scanf("%d %d %d", &l, &r, &v);
			change(l, r, 1, n, v,1);
		}
		printf("Case %d: The total value of the hook is %d.\n",cont++, query(1,n,1,n,1));
	}	
	return 0;
} 
发布了52 篇原创文章 · 获赞 2 · 访问量 855

猜你喜欢

转载自blog.csdn.net/qq_44714572/article/details/103933695