传送门:【HDU】4348 To the moon
题目分析:可以将标记留在节点上,查询的时候累加就行了,这样避免了可持久化线段树打标记内存吃紧的窘态。
my code:
#include <stdio.h> #include <algorithm> #include <string.h> using namespace std ; typedef long long LL ; #define rep( i , a , b ) for ( int i = ( a ) ; i < ( b ) ; ++ i ) #define For( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i ) #define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i ) #define clr( a , x ) memset ( a , x , sizeof a ) #define mid ( ( l + r ) >> 1 ) #define lson l , m #define rson m + 1 , r #define rt l , r const int MAXN = 100005 ; struct Node { Node* L , *R ; int addv ; LL sumv ; void pushup ( int l , int r ) { sumv = L->sumv + R->sumv + ( LL ) addv * ( r - l + 1 ) ; } } ; typedef Node* P_Node ; Node node[MAXN * 40] ; P_Node root[MAXN] , cur ; int n , m ; void build ( P_Node& o , int l , int r ) { o = ++ cur ; o->addv = 0 ; if ( l == r ) { scanf ( "%I64d" , &o->sumv ) ; return ; } int m = mid ; build ( o->L , lson ) ; build ( o->R , rson ) ; o->pushup ( rt ) ; } void update ( P_Node& now , P_Node old , int L , int R , int v , int l , int r ) { now = ++ cur ; *now = *old ; if ( L <= l && r <= R ) { now->addv += v ; now->sumv += ( LL ) v * ( r - l + 1 ) ; return ; } int m = mid ; if ( L <= m ) update ( now->L , old->L , L , R , v , lson ) ; if ( m < R ) update ( now->R , old->R , L , R , v , rson ) ; now->pushup ( rt ) ; } LL query ( P_Node o , int L , int R , int addv , int l , int r ) { if ( L <= l && r <= R ) return o->sumv + ( LL ) addv * ( r - l + 1 ) ; int m = mid ; addv += o->addv ; if ( R <= m ) return query ( o->L , L , R , addv , lson ) ; if ( m < L ) return query ( o->R , L , R , addv , rson ) ; return query ( o->L , L , R , addv , lson ) + query ( o->R , L , R , addv , rson ) ; } void solve () { char op[5] ; int l , r , d , t ; int T = 0 ; cur = node ; build ( root[0] , 1 , n ) ; while ( m -- ) { scanf ( "%s" , op ) ; if ( op[0] == 'C' ) { scanf ( "%d%d%d" , &l , &r , &d ) ; ++ T ; update ( root[T] , root[T - 1] , l , r , d , 1 , n ) ; } else if ( op[0] == 'Q' ) { scanf ( "%d%d" , &l , &r ) ; printf ( "%I64d\n" , query ( root[T] , l , r , 0 , 1 , n ) ) ; } else if ( op[0] == 'H' ) { scanf ( "%d%d%d" , &l , &r , &t ) ; printf ( "%I64d\n" , query ( root[t] , l , r , 0 , 1 , n ) ) ; } else scanf ( "%d" , &T ) ; } } int main () { while ( ~scanf ( "%d%d" , &n , &m ) ) solve () ; return 0 ; }