POJ3468 A Simple Problem with Integers(线段树区间修改--动态实现)
2016-07-25 22:32
453 查看
A Simple Problem with Integers
You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval. Input The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000. The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000. Each of the next Q lines represents an operation. "C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000. "Q a b" means querying the sum of Aa, Aa+1, ... , Ab. Output You need to answer all Q commands in order. One answer in a line. Sample Input 10 5 1 2 3 4 5 6 7 8 9 10 Q 4 4 Q 1 10 Q 2 4 C 3 6 3 Q 2 4 Sample Output 4 55 9 15 Hint The sums may exceed the range of 32-bit integers. Source POJ Monthly--2007.11.25, Yang Yi |
这里引入了懒惰更新,也叫延迟更新。
只有当拓展到子节点时,才向下更新,否则直接推出sum返回
动态的写法挺长的,不过相对好理解。
等以后学了静态的实现方法在补上静态的实现方法
#include <cstdio> #include <cstring> #include <algorithm> #include <utility> using namespace std; typedef long long LL; const int MAXN = 1E2 + 5; struct Node { int start, end; LL sum, add; Node* left, *right; Node(int start = 0, int end = 0) { this->start = start; this->end = end; sum = add = 0; left = right = NULL; } ~Node() { if (left != NULL) { delete left; } if (right != NULL) { delete right; } left = right = NULL; } } *tree; Node* Build(int start, int end) { Node* p = new Node(start, end); if (start != end) { int mid = (start + end) / 2; p->left = Build(start, mid); p->right = Build(mid + 1, end); } return p; } void PushDown(Node* node) { if (node->add) { node->left->sum += node->add * (node->left->end - node->left->start + 1); node->left->add += node->add; node->right->sum += node->add * (node->right->end - node->right->start + 1); node->right->add += node->add; node->add = 0; } } void PushUp(Node* node) { node->sum = node->left->sum + node->right->sum; } void Update(Node* node, int pos, int val) { if (node->start == node->end) { node->sum = val; return; } PushDown(node); if (node->left->end >= pos) { Update(node->left, pos, val); } else { Update(node->right, pos, val); } PushUp(node); } void Update(Node* node, int start, int end, int val) { if (node->start == start && node->end == end) { node->add += val; node->sum += val * (end - start + 1); return; } PushDown(node); if (node->left->end >= end) { Update(node->left, start, end, val); } else if (node->right->start <= start) { Update(node->right, start, end, val); } else { Update(node->left, start, node->left->end, val); Update(node->right, node->right->start, end, val); } PushUp(node); } LL Query(Node* node, int start, int end) { if (node->start == start && node->end == end) { return node->sum; } PushDown(node); LL sum = 0; if (node->left->end >= end) { sum = Query(node->left, start, end); } else if (node->right->start <= start) { sum = Query(node->right, start, end); } else { sum = Query(node->left, start, node->left->end); sum += Query(node->right, node->right->start, end); } PushUp(node); return sum; } int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif int n, m; while (scanf("%d%d", &n, &m) != EOF) { tree = Build(1, n); for (int i = 1, v; i <= n; ++i) { scanf("%d", &v); Update(tree, i, v); } char cmd[5]; int u, v, w; while (m--) { scanf("%s", cmd); switch (cmd[0]) { case 'C': scanf("%d%d%d", &u, &v, &w); Update(tree, u, v, w); break; case 'Q': scanf("%d%d", &u, &v); printf("%lld\n", Query(tree, u, v)); } } delete tree; } return 0; }
相关文章推荐
- 简单的四则运算
- 数的奇偶性
- ACMer博客瀑布流分析
- ACM程序设计大赛题目分类
- 2015年acm国内排名
- 计算字符串最后一个单词长度
- ACM网址
- 1272 小希的迷宫
- 1272 小希的迷宫
- hdu 1250 大数相加并用数组储存
- 矩阵的乘法操作
- 蚂蚁爬行问题
- 蚂蚁爬行问题
- 求两个数的最大公约数【ACM基础题】
- 打印出二进制中所有1的位置
- 杭电题目---一只小蜜蜂
- HDOJ 1002 A + B Problem II (Big Numbers Addition)
- 初学ACM - 半数集(Half Set)问题 NOJ 1010 / FOJ 1207
- 初学ACM - 组合数学基础题目PKU 1833
- POJ ACM 1002