P3372 【模板】线段树 1
题目
P3372 【模板】线段树 1
标签
题目描述
如题,已知一个数列,你需要进行下面两种操作:
- 将某区间每一个数加上 kk。
- 求出某区间每一个数的和。
输入格式
第一行包含两个整数 n, mn,m,分别表示该数列数字的个数和操作的总个数。
第二行包含 nn 个用空格分隔的整数,其中第 ii 个数字表示数列第 ii 项的初始值。
接下来 mm 行每行包含 33 或 44 个整数,表示一个操作,具体如下:
1 x y k
:将区间 [x, y][x,y] 内每个数加上 kk。2 x y
:输出区间 [x, y][x,y] 内每个数的和。
输出格式
输出包含若干行整数,即为所有操作 2 的结果。
输入输出样例
输入 #1
5 5 1 5 4 2 3 2 2 4 1 2 3 2 2 3 4 1 1 5 1 2 1 4
输出 #1
11 8 20
说明/提示
对于 30% 的数据:n≤8,m≤10。
对于 70% 的数据:n≤103,m≤104。
对于 100% 的数据:1≤n,m≤105。
保证任意时刻数列中任意元素的和在 [-263, 263)内。
【样例解释】
代码
不多说了,线段树板子题。
#include <bits/stdc++.h> using namespace std; const int MAXN = 1000090; long long nums[MAXN]; long long totN; long long totDO; bool tempquest; struct Node { long long tag; long long value; long long l, r; Node* lch, * rch; inline void maketag(const long long w) { value += (r - l + 1) * w; tag += w; } inline void push_up() { value = lch->value + rch->value; } inline void push_down() { if (!tag) { return; } else { if (lch==NULL) { Node(l, (l + r) >> 1); } if (rch == NULL) { Node(((l + r) >> 1) + 1, r); } lch->maketag(tag); rch->maketag(tag); tag = 0; } } Node(const long long L, const long long R) { l = L; r = R; if (l == r) { value = nums[l]; lch = NULL; rch = NULL; tag = 0; } else { tag = 0; long long mid = (l + r) >> 1; lch = new Node(L, mid); rch = new Node(mid + 1, R); push_up(); } } inline bool in_range(const long long L, const long long R) { return (L <= l) && (R >= r); } inline bool out_of_range(const long long L, const long long R) { return (l > R) || (r < L); } inline void update(const long long L, const long long R, const long long w) { if (in_range(L, R)) { maketag(w); } else if (!out_of_range(L, R)) { push_down(); lch->update(L, R, w); rch->update(L, R, w); push_up(); } } inline long long quest_range_sum(const long long L, const long long R) { if (in_range(L, R)) { return value; } else { if (out_of_range(L, R)) { return 0; } } push_down(); return lch->quest_range_sum(L, R) + rch->quest_range_sum(L, R); } }; inline long long read() { long long x = 0; short f = 1; char ch = getchar(); while (ch < '0' || ch>'9') { if (ch == '-') f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar(); } return x * f; } void write(const long long& x) { char f[100]; long long tmp = x; if (tmp < 0) { tmp = -tmp; putchar('-'); } long long s = 0; while (tmp > 0) { f[s++] = tmp % 10 + '0'; tmp /= 10; } while (s > 0) { putchar(f[--s]); } } int main() { totN = read(); totDO = read(); int temp; for (int i = 1; i <= totN; i++) { nums[i] = read(); } Node* root = new Node(1, totN); for (int i = 1; i <= totDO; i++) { tempquest = read() - 1; if (!tempquest) { long long tempL = read(); long long tempR = read(); auto tempW = read(); root->update(tempL, tempR, tempW); } else { auto tempL = read(); auto tempR = read(); write(root->quest_range_sum(tempL, tempR)); putchar('\n'); } } return 0; }//LikiBlaze Code