2015 UESTC Training for Data Structures

B - 秋实大哥与花

  线段树入门题,需要理解lazy思想。线段树这玩意,要理解还是不难,就是代码实现细节。。本渣写了几次了还是记不住。

  DEBUG LIST(Reversed):

  a) 读入数据的时候是0-based 即从a[0]~a[n-1] 但是在buildTree中赋值却使用1-based tree[i].val = a[l] = a[r] 

  b) 很容易搞错的地方,代入的数据是参数l,r还是这个结点的l,r(tree[idx].l, tree[idx].r)

  c) lazy tag分解具体操作(lazy tag意义可以是维护了这个区间sum之后记录的tag,只需要分解到子结点,我的就是这样,也可以是还没有维护这个线段的tag,需要在分解时维护该线段):将tag pushdown 至两个子结点,维护子线段的sum,维护子线段的lazy tag,将该线段lazy tag置为0

  0) update操作可以和query操作合并

#include <iostream>
#include <cstdio>
#include <cstdlib>

using namespace std;

const int MAXN = 1e5 + 50;

struct Tree{
    int    l, r; 
    long long val, lazy;

    void pushdown(long long v) {
        val += v*(r-l+1);
        lazy += v;
    }
}tree[5*MAXN];

int n, m;
int a[MAXN];

void buildTree(int l, int r, int idx)
{
//    if (l > r)    return 0;
    tree[idx].l = l;
    tree[idx].r = r;
    if (l == r)     tree[idx].val = a[l];
    else {
        int mid = (l + r) / 2;
        buildTree(l, mid, idx*2);
        buildTree(mid+1, r, idx*2+1);
        tree[idx].val = tree[idx*2].val + tree[idx*2+1].val;
    }
}

long long query(int l, int r, long long v, int idx)
{
//    if (l > r)    return 0;
    if (l == tree[idx].l && r == tree[idx].r) {
        tree[idx].lazy += v;
        tree[idx].val += v*(r-l+1);
        return tree[idx].val;
    }
    else {
        int mid = (tree[idx].l + tree[idx].r) / 2;
//        long long t = 0;
        tree[idx].val += (r-l+1)*v;
        if (tree[idx].lazy != 0)    {
            tree[idx*2].pushdown(tree[idx].lazy);
            tree[idx*2+1].pushdown(tree[idx].lazy);
            tree[idx].lazy = 0;
        }
        if (r <= mid)    
            return query(l, r, v, idx*2);
        else if (l >= mid+1)
            return query(l, r, v, idx*2+1);
        else
            return query(l, mid, v, idx*2) + query(mid+1, r, v, idx*2+1);
    }
}

int main()
{
#ifdef LOCAL
    freopen("B.in", "r", stdin);
#endif
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
        scanf("%d", a+i);
    scanf("%d", &m);
    buildTree(1, n, 1);
    while (m--) {
        int l, r, v;
        scanf("%d%d%d", &l, &r, &v);
        printf("%lld
", query(l, r, v, 1));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/gemmeg/p/4433254.html