線分樹(区間更新と区間照会)——Just a Hook(HDU 1698)


  • テーマリンク:http://acm.hdu.edu.cn/showproblem.php?pid=1698
  • 分析&題解:多くなくても、これらの水問題はテンプレート
  • を置いています.
    1.線分樹の標準前処理:
    #define lc (d<<1)
    #define rc (d<<1|1)
    #define mid ( l+r >>1)
    //l,r        
    2.ツリー:
    #define Max 100005
    
    int a[Max];
    
    struct Tr
    {
        int sum, lz;//   ,   
    }tr[Max<<2];
    
    void Push(int root)
    {
        tr[d].sum = tr[lc].sum + tr[rc].sum;
    }
    
    void build (int root, int l, int r)
    {
        tr[root].lz = 0;
        if( l == r )
        {
            tr[root].sum = a[l];
            return ;
        }
        build(lc, l, mid);
        build(rc, mid+1, r);
        Push(root);
    }
    2.怠惰な操作:区間の合計なので、区間の更新後にはステップ怠惰な操作が必要です.全区間の和を更新します.
    void lazy(int root, int l, int r)
    {//if(tr[root].lz)
        {
            tr[lc].lz = tr[root].lz;
            tr[rc].lz = tr[root].lz;
            tr[lc].sum = tr[root].lz*(mid-l+1);
            tr[rc].sum = tr[root].lz*(r-mid);
            tr[root].lz = 0;
        }
    }
    3.区間更新:
    void update (int root,  int l,  int r,  int L,  int R,  int k)
    {
        if(l == L && r == R)//       ,      
        {
            tr[root].lz = k;
            tr[root].sum = k*(r-l+1);
            return ;
        }
        lazy(root, l, r);
        if( R <= mid) update(lc, l, mid, L, R, k);
        else if(L > mid) update( rc, mid+1, r, L, R, k);
        else
        {
            update(lc, l, mid, L, mid, k);
            update(rc, mid+1, r, mid+1, R, k);
        }
        Push(root);
    }
    4.区間照会:
    int query(int root,  int l ,  int r,  int L,  int R )
    {
        if( l == L && r == R)
        {
            return tr[root].sum;
        }
        lazy(d, l, r);
        if( R <= mid) return query(lc, l, mid, L, R);
        else if (L > mid) return query( rc, mid+1, r, L, R);
        else return query(lc, l, mid, L, mid) + query(rc, mid+1, r, mid+1, R);
    }
  • ACコード:
  • #include 
    #include 
    #include 
    #include 
    
    using namespace std;
    
    #define lc (d<<1)
    #define rc (d<<1|1)
    #define mid ( l+r >>1)
    #define Max 100005
    
    int a[Max];
    
    struct Tr
    {
        int sum, lz;
    }tr[Max<<2];
    
    void Push(int d)
    {
        tr[d].sum = tr[lc].sum + tr[rc].sum;
    }
    
    void build (int d, int l, int r)
    {
        tr[d].lz = 0;
        if( l == r )
        {
            tr[d].sum = a[l];
            return ;
        }
        build(lc, l, mid);
        build(rc, mid+1, r);
        Push(d);
    }
    
    void lazy(int d, int l, int r)
    {
        if(tr[d].lz)
        {
            tr[lc].lz = tr[d].lz;
            tr[rc].lz = tr[d].lz;
            tr[lc].sum = tr[d].lz*(mid-l+1);
            tr[rc].sum = tr[d].lz*(r-mid);
            tr[d].lz = 0;
        }
    }
    
    int query(int d,  int l ,  int r,  int L,  int R )
    {
        if( l == L && r == R)
        {
            return tr[d].sum;
        }
        lazy(d, l, r);
        if( R <= mid) return query(lc, l, mid, L, R);
        else if (L > mid) return query( rc, mid+1, r, L, R);
        else return query(lc, l, mid, L, mid) + query(rc, mid+1, r, mid+1, R);
    }
    
    void update (int d,  int l,  int r,  int L,  int R,  int k)
    {
        if(l == L && r == R)
        {
            tr[d].lz = k;
            tr[d].sum = k*(r-l+1);
            return ;
        }
        lazy(d, l, r);
        if( R <= mid) update(lc, l, mid, L, R, k);
        else if(L > mid) update( rc, mid+1, r, L, R, k);
        else
        {
            update(lc, l, mid, L, mid, k);
            update(rc, mid+1, r, mid+1, R, k);
        }
        Push(d);
    }
    
    int main()
    {
        int T;
        scanf("%d", &T);
        int tt = 1;
        while(T--)
        {
            int N,Q;
            scanf("%d%d", &N, &Q);
            for(int i=1;i<=N;i++)
                a[i] = 1;
            build(1, 1, N);
            for(int i=1;i<=Q;i++)
            {
                int a,b,v;
                scanf("%d%d%d", &a,&b,&v);
                update(1, 1, N, a, b, v);
            }
            printf("Case %d: The total value of the hook is %d.
    "
    , tt++, query(1, 1, N, 1, N)); } }