HDU1556 线段树

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define mxn 100020
int ll[mxn << 2], rr[mxn << 2], sum[mxn << 2], add[mxn << 2];
//建树
void build( int l, int r, int i ) {
	rr[i] = r, ll[i] = l;
	if( l == r ) {
		sum[i] = 0;
		return ;
	}
	int m = ( l + r ) >> 1, ls = i << 1, rs = ls | 1;
	build( l, m ,ls );
	build( m+1, r, rs );
	sum[i] = sum[ls] + sum[rs];
}
//单点更新
void update( int k, int v, int i ) {    
	if( ll[i] == rr[i] ) {
		sum[ll[i]] = v;
		return ;
	}
	int m = ( ll[i] + rr[i] ) >> 1, ls = i << 1, rs = ls | 1;
	if( k <= m )
		update( k, v, ls );
	else
		update( k, v, rs );
	sum[i] = sum[ls] + sum[rs];
}
//向下释放标记
void PushDown( int i, int m ) {
	if( add[i] ) {
		int ls = i << 1, rs = ls | 1;
		add[ls] += add[i];
		add[rs] += add[i];
		sum[ls] += add[i] * ( m - ( m >> 1) ); //位运算优先级竟然比减号低,被坑了好久!!
		sum[rs] += add[i] * ( m >> 1 );
		add[i] = 0;
	}
}
//区间查询
int find( int l, int r, int i ) {
	if( l == ll[i] && r == rr[i] ) {
		return sum[i];
	}
	PushDown( i, rr[i] - ll[i] + 1 );
	int m = ( ll[i] + rr[i]) >> 1, ls = i << 1, rs = ls | 1;
	if( r <= m )
		return find( l, r, ls );
	if( l > m )
		return find( l, r, rs );
	return find( l, m, ls ) + find( m+1, r, rs );
}
//区间更新
void update( int c, int l, int r, int i ) {
	if( l == ll[i] && r == rr[i] ) {
		add[i] += c;
		sum[i] += c * ( r - l + 1 );
		return ;
	}
	if( ll[i] == rr[i] ) return ;
	int m = ( ll[i] + rr[i] ) >> 1, ls = i << 1, rs = ls | 1;
	if( r <= m ) 
		update( c, l, r, ls );
	else
		if( l > m )
			update( c, l, r, rs );
		else {
			update( c, l, m, ls );
			update( c, m+1, r, rs );
		}
	sum[i] = sum[ls] + sum[rs];
}
int main() {
	int n;
	while( scanf("%d",&n) && n ) {
		memset( add, 0 ,sizeof( add ) );
		build( 1, n, 1 );
		int x, y;
		for( int i = 1; i <= n; ++i ) {
			scanf( "%d%d", &x, &y );
			update( 1, x, y, 1 );
		}
		printf( "%d", find( 1, 1, 1 ) );
		for( int i = 2; i <= n; ++i ) {
			printf( " %d", find( i, i, 1 ) );
		}
		printf( "\n" );
	}
	return 0;
}

你可能感兴趣的:(HDU1556 线段树)