1. 程式人生 > >hdu 1698 Just a Hook(線段樹的區間更新及求和)

hdu 1698 Just a Hook(線段樹的區間更新及求和)

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define N 100010
struct Node{
    int L;
    int R;
    int V;
}tree[4*N];
void BuildTree(int root,int l,int r){
    tree[root].L=l;
    tree[root].R=r;
    tree[root].V=1;///表示顏色,該顏色預設價值為1
    if(l==r){
        return ;
    }
    int mid=(l+r)/2;
    BuildTree(2*root,l,mid);
    BuildTree(2*root+1,mid+1,r);
}
void update(int root,int s,int e,int a){
    if(tree[root].V==a){///區間內的顏色與要更新的一樣,不用更新
        return ;
    }
    if(tree[root].L==s&&tree[root].R==e){///區間相同,直接更新
        tree[root].V=a;
        return ;
    }
    if(tree[root].V!=-1){///如果區間的顏色相同,但是與即將跟新的顏色不一樣,則此區間就要變成雜色
        tree[2*root].V=tree[2*root+1].V=tree[root].V;
        ///先將區間的顏色更新到子結點
        ///因為每次更新只更新到父節點,如果第二組資料要用到子節點時,就應該先將父節點的顏色給子節點,再標記
        tree[root].V=-1;///區間此時不只有一種顏色了,標記為-1
    }
    int mid=(tree[root].L+tree[root].R)/2;
    if(e<=mid) update(2*root,s,e,a);
    else if(s>mid) update(2*root+1,s,e,a);
    else {
        update(2*root,s,mid,a);
        update(2*root+1,mid+1,e,a);
    }
}
int Query(int root,int s,int e){
    if(tree[root].V!=-1){///區間都為同一顏色
        return (e-s+1)*tree[root].V;
    }
    else{
        int mid=(tree[root].L+tree[root].R)/2;
        if(e<=mid) return Query(2*root,s,e);
        else if(s>mid) return Query(2*root+1,s,e);
        else {
            return Query(2*root,s,mid)+Query(2*root+1,mid+1,e);
        }
    }
}
int main(){
    int T,ca=1;
    scanf("%d",&T);
    while(T--){
        int n;
        scanf("%d",&n);
        BuildTree(1,1,n);
        int m;
        scanf("%d",&m);
        while(m--){
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            update(1,a,b,c);
        }
        printf("Case %d: The total value of the hook is %d.\n",ca++,Query(1,1,n));
    }
    return 0;
}