hihocoder1078 线段树的区间修改(线段树)

题目链接:http://hihocoder.com/problemset/problem/1078

线段树区间求和,区间更新。

#include <iostream>
#include <cstdio>
using namespace std;

const int MAX_N = 1e5 + 5;

int seg_n;
int seg[MAX_N << 2];
// 标记数组  标记区间是否需要被更新 
int flg[MAX_N << 2];

void init( int n_ ) {
	seg_n = 1; 
	while ( seg_n < n_ ) seg_n <<= 1;
}

// 单点更新 
void update( int k, int x ) {   
    k += seg_n-1;
	int diff = x-seg[k];  
    seg[k] = x;  
    while ( k > 0 ) {  
        k = (k-1)/2;  
        seg[k] += diff;  
    }  
} 

void pushdown( int k, int l, int r ) {
	// 叶子节点 不再更新子节点 
	if ( r-l == 1 ) return;
	// 否则更新区间值  并标记区间 
	int mid = (l+r) >> 1;
	flg[2*k+1] = flg[k];
	seg[2*k+1] = (mid-l)*flg[k];
	
	flg[2*k+2] = flg[k];
	seg[2*k+2] = (r-mid)*flg[k];
	
	// 去除父区间标记 
	flg[k] = 0;
} 

void pushup( int k ) {
	seg[k] = seg[2*k+1] + seg[2*k+2];
}

// 区间更新 不是简单的遍历区间每个点进行单点更新 这样会 tle
// 区间更新的思想是 添加一个标记数组 标记某个区间是否要被更新
// 更新时 并不直接更新叶子节点  而是先更新一次区间值  供查询时使用
// 如果查询时 需要查询该区间子区间的值时  再把这个更新落实下去 
// 这样更新被延迟到了不得不更新的时候  
// 有时候不需要再访问的时候  这次更新就被优化掉了 
void update( int a, int b, int x, int k, int l, int r ) {
	if ( a >= r || b <= l ) return;
	if ( a <= l && b >= r ) {
		seg[k] = (r-l)*x; 
		// [l,r] 对应区间节点 k  标记值x  
		flg[k] = x;
		return ;
	}
	
	// 如果这个区间被标记了 并且接下来要使用更新后的值 则把这次更新落实下去 
	if ( flg[k] ) pushdown( k, l, r );
	
	update( a, b, x, 2*k+1, l, (l+r)/2 );
	update( a, b, x, 2*k+2, (l+r)/2, r ); 
	
	// 更新两个子节点后 更新当前结点值 
	pushup(k);
} 

int query( int a, int b, int k, int l, int r ) {
	if ( a >= r || b <= l ) return 0;
	if ( a <= l && b >= r ) return seg[k];
	else {
		// 查询时也需要一次更新 但不需要 pushup 
		if ( flg[k] ) pushdown( k, l, r ); 
		return query(a,b,2*k+1,l,(l+r)/2) + query(a,b,2*k+2,(l+r)/2,r);
	}
}

int main()
{
	int N, M;
	int op, l, r, x;
	scanf( "%d", &N );
	init( N );
	
	for ( int i = 0 ; i < N ; ++ i ) {
		scanf( "%d", &x );
		update( i, x );
	}
//	cout << seg[0] << endl;
	scanf("%d", &M);
	for ( int i = 0 ; i < M ; ++ i ) {
		scanf( "%d", &op );
		if ( op == 1 ) {
			scanf( "%d%d%d", &l, &r, &x );
			update( l-1, r, x, 0, 0, seg_n );
		} else {
			scanf( "%d%d", &l, &r );
			printf( "%d\n", query( l-1, r, 0, 0, seg_n ) );
		}
	}
	
	return 0;
}


猜你喜欢

转载自blog.csdn.net/hopygreat/article/details/79553166