poj 3468(线段树)

来源:互联网 发布:windows活动目录管理 编辑:程序博客网 时间:2024/04/28 06:11

题意:一个数字序列,Q a b查询a到b的数字和,C a b c从a到b都加c。

题解:区间修改水题。

#include <stdio.h>#include <string.h>const int N = 100005;long long addv[N << 2], sum[N << 2], x;int n, q, l1, r1;void pushup(int k, int left, int right) {sum[k] = sum[k * 2] + sum[k * 2 + 1];}void pushdown(int k, int left, int right) {int len = right - left + 1;if (addv[k]) {addv[k * 2] += addv[k];addv[k * 2 + 1] += addv[k];sum[k * 2] += addv[k] * (len - len / 2);sum[k * 2 + 1] += addv[k] * (len / 2);addv[k] = 0;}}void build(int k, int left, int right) {addv[k] = 0;if (left == right) {scanf("%lld", &sum[k]);return;}int mid = (left + right) / 2;build(k * 2, left, mid);build(k * 2 + 1, mid + 1, right);pushup(k, left, right);}void update(int k, int left, int right) {if (l1 <= left && right <= r1) {addv[k] += x;sum[k] += x * (right - left + 1);return;}pushdown(k, left, right);int mid = (left + right) / 2;if (l1 <= mid)update(k * 2, left, mid);if (r1 > mid)update(k * 2 + 1, mid + 1, right);pushup(k, left, right);}long long query(int k, int left, int right) {if (l1 <= left && right <= r1)return sum[k];pushdown(k, left, right);int mid = (left + right) / 2;long long res = 0;if (l1 <= mid)res += query(k * 2, left, mid);if (r1 > mid)res += query(k * 2 + 1, mid + 1, right);return res;}int main() {while (scanf("%d%d", &n, &q) == 2) {build(1, 1, n);char str[5];while (q--) {scanf("%s%d%d", str, &l1, &r1);if (str[0] == 'Q')printf("%lld\n", query(1, 1, n));else if (str[0] == 'C') {scanf("%lld", &x);getchar();update(1, 1, n);}}}return 0;}


0 0
原创粉丝点击