标签:
题目链接:http://poj.org/problem?id=3468
思路分析:使用sumv[i]记录一段线段区间的目前的sum,addv[i]记录在整个过程中对某一段线段区间上的所有增加值的和;
更新操作:将需要更新的区间分为多段不相交的区间,并在这些区间上更新该区间上增加的值,并修改这些区间的sum值以及其父节点的sum值;
查询操作:使用全局变量sum_ans,将查询的区间分为多段不相交的区间,并且进行增加的值的传递,将增加的值传给子节点,将这些区间的值
加上传递的增加的值即为所求;
代码如下:
#include <cstdio> #include <iostream> using namespace std; const int MAX_N = 2 * 1000000 + 100; long long sumv[MAX_N], addv[MAX_N]; long long sum_ans, arr[MAX_N]; void Build(int root, int l, int r, long long arr[]) { if (l == r) { addv[root] = arr[l]; sumv[root] = arr[l]; } else { int mid = (l + r) / 2; Build(2 * root, l, mid, arr); Build(2 * root + 1, mid + 1, r, arr); sumv[root] = sumv[2 * root] + sumv[2 * root + 1]; } } void Updata(int o, int l, int r, long long add_value, int ql, int qr) { if (l > qr || r < ql) return; if (ql <= l && r <= qr) addv[o] += add_value; else { int mid = (l + r) / 2; Updata(2 * o, l, mid, add_value, ql, qr); Updata(2 * o + 1, mid + 1, r, add_value, ql, qr); } sumv[o] = 0; if (l < r) sumv[o] = sumv[2 * o] + sumv[2 * o + 1]; sumv[o] += addv[o] * (r - l + 1); } void Query(int o, int l, int r, int ql, int qr, long long add) { if (l > qr || r < ql) return; if (ql <= l && r <= qr) sum_ans += sumv[o] + add * (r - l + 1); else { int mid = (l + r) / 2; Query(2 * o, l, mid, ql, qr, add + addv[o]); Query(2 * o + 1, mid + 1, r, ql, qr, add + addv[o]); } } int main() { int num, query_times; scanf("%d %d", &num, &query_times); for (int i = 1; i <= num; ++i) scanf("%lld", &arr[i]); Build(1, 1, num, arr); for (int i = 0; i < query_times; ++i) { char str[2]; int ql, qr, add_value; scanf("%s", str); if (str[0] == ‘Q‘) { sum_ans = 0; scanf("%d %d", &ql, &qr); Query(1, 1, num, ql, qr, 0); printf("%lld\n", sum_ans); } else { scanf("%d %d %d", &ql, &qr, &add_value); Updata(1, 1, num, add_value, ql, qr); } } return 0; }
poj 3468 A Simple Problem with Integers(线段树)
标签:
原文地址:http://www.cnblogs.com/tallisHe/p/4564940.html