Problem Address:http://poj.org/problem?id=3468
【前言】
其实修改区域查询区域的情况是可以用树状数组求解的。
参考地址:http://blog.csdn.net/Human_CK/archive/2011/06/13/6542370.aspx
出于学习线段树的目的,所以用了线段树。
【思路】
线段树前面也有写过,这里不多说了。
主要点是,每个节点记录对应区间的总和并维护其准确性,并且用变量add记录对这个节点区间每个节点的相同增值。
更新的时候,从上往下更新。
如果吻合区间则增值增加。否则递归求解。
查询的时候,从上往下查。
如果刚好吻合,则返回其上对这个区间所有增值的总和+这个区间的总和。
如果不吻合则递归下去。
【代码】
#include <iostream> using namespace std; const int maxn = 100000; __int64 num[maxn+10]; struct node { int l, r; node *pl, *pr; __int64 sum; __int64 add; }tree[maxn*3]; int total; node *new_node() { node *p = &tree[total]; total++; memset(p, 0, sizeof(node)); return p; } node *build(int l, int r) { node *root = new_node(); root->l = l; root->r = r; if (r>l) { int mid = (l+r)/2; root->pl = build(l, mid); root->pr = build(mid+1, r); } if (l==r) root->sum = num[l]; else root->sum = root->pl->sum + root->pr->sum; return root; } void update(node *root, int l, int r, int v) { if (root->l==l && root->r==r) { root->add += v; return; } root->sum += (r-l+1)*v; int mid = (root->l+root->r)/2; if (r<=mid) update(root->pl, l, r, v); else if (l>mid) update(root->pr, l, r, v); else { update(root->pl, l, mid, v); update(root->pr, mid+1, r, v); } } __int64 getsum(node *root, int l, int r, __int64 temp) { temp += root->add; if (root->l==l && root->r==r) return root->sum + (r-l+1)*temp; int mid = (root->l+root->r)/2; if (r<=mid) return getsum(root->pl, l, r, temp); else if (l>mid) return getsum(root->pr, l, r, temp); else return getsum(root->pl, l, mid, temp) + getsum(root->pr, mid+1, r, temp); } int main() { int n,m; int a,b,c; char cmd[2]; int i; node *root; scanf("%d %d", &n, &m); for (i=1; i<=n; i++) scanf("%I64d", &num[i]); total = 0; root = build(1, n); for (i=0; i<m; i++) { scanf("%s", cmd); if (cmd[0]=='Q') { scanf("%d %d", &a, &b); printf("%I64d/n", getsum(root, a, b, 0)); } else { scanf("%d %d %d", &a, &b, &c); update(root, a, b, c); } } return 0; }
【P.S】
话说线段树的代码也不是特别复杂= =