#include

线段树:延迟标记,区间更新(赋值)求总和

/* 延迟标记,区间更新(赋值)求总和 , HDU1698 */
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std ;

#define maxn 2000000

struct node {
    int le ;
    int ri ;
    int sum , flag ;
};

node tree[maxn] ;

//建树
void build(int root , int le , int ri){
    tree[root].le = le ;
    tree[root].ri = ri ;
    tree[root].flag = 0 ;
    tree[root].sum = (le - ri + 1 ) ;
    
    if(le == ri ){
        return;
    }
    
    int mid = (le + ri) /2 ;
    build(root*2 , le , mid) ;
    build(root*2+1 , mid+1 , ri) ;
}

//更新
void update(int le , int ri , int flag , int root){
    if(ri < tree[root].le || tree[root].ri < le){
        // 更新区间  [le , ri ] 不在根节点范围
        return;
    }
    
    if(le <= tree[root].le  &&  tree[root].ri<=ri){
        // 查询区间被包含
        tree[root].flag = flag ;
        tree[root].sum = (tree[root].ri - tree[root].le + 1) * tree[root].flag ;
        return;  
    }
    // 子过程用到被标记的 数段 时  延迟标记向下传递
    if(tree[root].flag!=0){
        int ll = root*2 , rr = root*2+1 ;
        tree[ll].flag = tree[root].flag ;
        tree[ll].sum  = (tree[ll].ri - tree[ll].le+1) * tree[ll].flag ;
        
        tree[rr].flag = tree[root].flag ;
        tree[rr].sum = (tree[rr].ri - tree[rr].le + 1) * tree[rr].flag ;
        tree[root].flag = 0 ;
    }
    
    update(le , ri , flag , root*2) ;
    update(le , ri , flag , root*2+1) ;
    //子节点更改父亲
    tree[root].sum = tree[root*2].sum + tree[root*2+1].sum ;
}

int main(){
    
    int t ;
    int n , m ;
    int x , y , z ;
    scanf("%d" , &t) ;
    while(t--){
        scanf("%d%d", &n , &m) ;
        //建立根节点为 1 节点标号 1 -> n 的线段树  
        build(1,1,n) ;  
        
        for(int i=1 ; i<=m ; i++){
            scanf("%d%d%d" , &x ,&y , &z) ;
            //节点x->y 赋值为 z
            update(x , y , z , 1) ;
        }
        // 整个线段树的和  
        printf("%d\n" , tree[1].sum) ;  
    }
    return  0 ;
} 

 

posted @ 2017-10-21 00:36  0一叶0知秋0  阅读(237)  评论(0)    收藏  举报