luogu P3372ybtoj线段树课堂过关例题2区间查改 &模板线段树 1
Posted SSL_ZZL
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu P3372ybtoj线段树课堂过关例题2区间查改 &模板线段树 1相关的知识,希望对你有一定的参考价值。
Link
luogu P3372 【模板】线段树 1
ybtoj【线段树课堂过关】【例题2】区间查改
题面//因为不知道侵不侵权所以就是题面是私密的,有账号的直接看转送门就可了
题目大意
如题,已知一个数列,你需要进行下面两种操作:
- 将某区间每一个数加上s。
- 求出某区间每一个数的和。
解题思路
模板带lazy标的线段树
对于每个需要修改的区间(例[1-2] + 5),并不寻找区间中单个单个的点([1-1] + 5,[2-2] + 5)
而是直接在区间上修改([1,2].s + 5 * 2),并且打上lazy标([1,2].lazy + 5)
等需要找区间中更小的区间时再把lazy标下传([1,1].s + 5,[1,1].lazy + 5;[2,2].s + 5,[2,2].lazy + 5)
Code
#include <iostream>
#include <cstdio>
#define ll long long
using namespace std;
struct DT{
ll s, lazy;
}tree[8001000];
int n, m, c, x, y;
int s, a[1001000];
void down(int root, int l, int r) { //下传lazy标
int mid = (l + r) / 2;
tree[root * 2].s += tree[root].lazy * (mid - l + 1);
tree[root * 2].lazy += tree[root].lazy;
tree[root * 2 + 1].s += tree[root].lazy * (r - (mid + 1) + 1);
tree[root * 2 + 1].lazy += tree[root].lazy;
tree[root].lazy = 0;
}
void build(int root, int l, int r) {
if(l == r) {
tree[root].s = a[l];
return;
}
int mid = (l + r) / 2;
build(root * 2, l, mid);
build(root * 2 + 1, mid + 1, r);
tree[root].s = tree[root * 2].s + tree[root * 2 + 1].s;
}
void add(int root, int l, int r, int x, int y, int s) {
if (l >= x && r <= y) {
tree[root].s += 1ll * s * (r - l + 1);
tree[root].lazy += s;
return;
}
down(root, l, r); //需要寻找更小的区间=>下传
int mid = (l + r) / 2;
if(x <= mid)
add(root * 2, l, mid, x, y, s);
if(y > mid)
add(root * 2 + 1, mid + 1, r, x, y, s);
tree[root].s = tree[root * 2].s + tree[root * 2 + 1].s;
}
ll find(int root, int l, int r, int x, int y) {
if (l >= x && r <= y) return tree[root].s;
down(root, l, r);
int mid = (l + r) / 2;
ll ans = 0;
if(x <= mid)
ans += find(root * 2, l, mid, x, y);
if(y > mid)
ans += find(root * 2 + 1, mid + 1, r, x, y);
return ans;
}
int main() {
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]);
build(1, 1, n);
for(int i = 1; i <= m; i++) {
scanf("%d %d %d", &c, &x, &y);
if(c == 1) {
scanf("%d", &s);
add(1, 1, n, x, y, s);
} else
printf("%lld\\n", find(1, 1, n, x, y));
}
}
以上是关于luogu P3372ybtoj线段树课堂过关例题2区间查改 &模板线段树 1的主要内容,如果未能解决你的问题,请参考以下文章
ybtoj 单调队列课堂过关luogu P1886例题1滑动窗口
luogu UVA10559 ybtoj 区间DP课堂过关 例题3消除木块 & 方块消除 Blocks
luogu P4170ybtoj 区间DP课堂过关 例题2木板涂色 & [CQOI2007]涂色