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\n", query(l, r, v, 1)); } return 0; }