线段树 POJ - 3468 A Simple Problem with Integers
地址 https://vjudge.ppsucxtt.cn/problem/POJ-3468
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.
解答 题目的大意是
给出一个整数数列, A[1] ~~ A[N]
有以下两个操作
1 Q a b 查询数组A[]中 索引a到索引b所有的数的和
2 C a b c 对数组A[]中 索引a到索引b的所有的数 全部加上一个数c
对于每个操作1的查询 打印出结果 结果占一行
对于线段树方案,这是一个区间更新 区间查询的方案。
对于区间更新,不能高效的实现对一段区域添加一个值,因为需要对这个区间相关的所有节点均进行更新
todo
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <assert.h>
#include <algorithm>
using namespace std;
const int N = 100010;
struct Node {
int l; int r;
long long sum;
long long add;
}t[4 * N];
int arr[N];
int n, m;
void build(int p, int l, int r) {
t[p].l = l; t[p].r = r;
if (l == r) { t[p].sum = arr[l]; return; }
int mid = (l + r) >> 1;
build(p * 2, l, mid);
build(p * 2 + 1, mid + 1, r);
t[p].sum = t[p * 2].sum + t[p * 2 + 1].sum;
}
void pushDown(int p) {
if (t[p].add) {
t[p * 2].sum += t[p].add*(t[p*2].r-t[p*2].l+1);
t[p * 2+1].sum += t[p].add*(t[p * 2+1].r - t[p * 2+1].l + 1);
t[p * 2].add += t[p].add;
t[p * 2+1].add += t[p].add;
t[p].add = 0;
}
}
void update(int p, int l, int r, int d) {
if (l <= t[p].l && r >= t[p].r) {
t[p].sum += (long long)d* (t[p].r - t[p].l + 1);
t[p].add += d;
return;
}
pushDown(p);
int mid = (t[p].l + t[p].r) >> 1;
if (l <= mid) update(p * 2, l, r, d);
if (r > mid) update(p * 2 + 1, l, r, d);
t[p].sum = t[p * 2].sum + t[p * 2 + 1].sum;
}
long long query(int p, int l, int r) {
if (l <= t[p].l && r >= t[p].r) return t[p].sum;
pushDown(p);
int mid = (t[p].l + t[p].r) >> 1;
long long val = 0;
if (l <= mid) val += query(p * 2, l, r);
if (r > mid) val += query(p * 2 + 1, l, r);
return val;
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++) {
scanf("%d",&arr[i]);
}
build(1, 1, n);
for (int i = 0; i < m; i++) {
char Q[2];
int j, k, l;
scanf("%s", &Q);
if (Q[0] == 'Q') {
scanf("%d%d",&j,&k);
printf("%lld\n", query(1,j,k));
}
else if(Q[0]=='C') {
scanf("%d%d%d", &j, &k,&l);
update(1,j,k,l);
}
else {
assert(0);
}
}
return 0;
}
标记永久化模式
// 111111111111.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
const int N = 100010;
struct SEGMENT_TREE {
int l; int r;
long long sum; long long tag;
}tr[N*4];
int n, q;
int arr[N];
void build(int p,int l,int r ) {
tr[p].l = l; tr[p].r = r;
if (l == r) {
tr[p].tag = 0;
tr[p].sum = arr[l];
return;
}
int mid = (l + r) >> 1;
build(p*2,l, mid);
build(p*2+1,mid + 1, r);
tr[p].sum = tr[p * 2].sum + tr[p*2+1].sum;
}
long long query(int p, int L, int R) {
int l = tr[p].l; int r = tr[p].r;
if (L <= l && r <= R)
return tr[p].sum;
int mid = (l + r) >> 1;
long long tot = tr[p].tag *(min(r, R) - max(l, L) + 1);
if (L <= mid) tot += query(p * 2, L, R);
if (mid < R) tot += query(p * 2 + 1, L, R);
return tot;
}
void update(int L, int R, int d, int p) {
int l = tr[p].l; int r = tr[p].r;
if (L <= l && r <= R) {
tr[p].tag += d;
tr[p].sum += d * (r - l + 1);
return;
}
int mid = (l + r) >> 1;
if (L <= mid) update(L, R, d, p*2);
if (mid < R) update(L, R, d, p*2+1);
// pushup 操作需要将当前节点内的标记也算上
tr[p].sum = tr[p*2].sum + tr[p*2+1].sum + tr[p].tag * (r - l + 1);
}
int main()
{
scanf("%d%d", &n, &q);
for (int i = 1; i <= n; i++) {
scanf("%d",&arr[i]);
}
build(1,1,n);
while (q--) {
char t[10];
int L, R, d;
scanf("%s%d%d", t, &L, &R);
if (t[0] == 'Q') {
printf("%lld\n", query(1,L, R));
}
else {
scanf("%d", &d);
update(L, R, d, 1);
}
}
return 0;
}
作 者: itdef
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力