(线段树,add懒标记)洛谷模板题

1|0原题链接:

洛谷模板题

2|0题目:

如题,已知一个数列,你需要进行下面两种操作:
1、将某区间每一个数加上 k。
2、求出某区间每一个数的和。
输入格式:
第一行包含两个整数 n,m,分别表示该数列数字的个数和操作的总个数。
第二行包含 n 个用空格分隔的整数,其中第 i 个数字表示数列第 i 项的初始值。
接下来 m 行每行包含 3 或 4 个整数,表示一个操作,具体如下:
1 x y k 表示将[x, y]区间内的数都加上k
2 x y 表示查询[x, y]区间内的总合
输出格式:
输出包含若干行整数,即为所有操作 2 的结果。
输入 #1      输出 #1
5 5         11
1 5 4 2 3      8
2 2 4        20
1 2 3 2
2 3 4
1 1 5 1
2 1 4

说明:
所有数据范围:1 ≤ n, m ≤ 1e5
答案在long long 范围内。

3|0思路:

  这题为什么要用线段树来写呢,那就是因为区间修改,区间查询了吧,如果是区间修改,单点查询,
用树状数组他不香吗,那么线段树的区间修改又涉及到了懒标记的运用。
 线段树的区间操作可以使用懒标记来优化时间复杂度,具体实现就得写一个pushdown函数,作用是将
懒标记的值传给他的儿子,这样就可以将查询前的n步操作化为一步,大大优化了时间复杂度,具体实现并
不复杂,重要的还是多练(我还是太菜了)。

#include<bits/stdc++.h> using namespace std; #define endl '\n' #define int long long typedef pair<int, int> PII; const int mod = 1e9 + 7; const int inf = 0x3f3f3f3f; const int N = 1e5 + 10; int n, m; int w[N]; struct Node{ int l, r; int sum, add; }tr[N << 2]; void pushup(int u){ tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum; } void pushdown(int u){ //pushdown操作里的sum += x我开始写成了 =,所有改了好久,痛心疾首 if(tr[u].add){ tr[u << 1].sum += (tr[u << 1].r - tr[u << 1].l + 1) * tr[u].add; tr[u << 1 | 1].sum += (tr[u << 1 | 1].r - tr[u << 1 | 1].l + 1) * tr[u].add; tr[u << 1].add += tr[u].add; tr[u << 1 | 1].add += tr[u].add; tr[u].add = 0; } } void build(int u, int l, int r){ tr[u].l = l, tr[u].r = r; if(l == r) tr[u].sum = w[l]; else{ int mid = l + r >> 1; build(u << 1, l, mid); build(u << 1 | 1, mid + 1, r); pushup(u); } } void modify(int u, int l, int r, int k){ //包含在指定区间内再操作,包含的运算符想清楚再写,就不会debug这么久 if(tr[u].l >= l && tr[u].r <= r){ tr[u].sum += (tr[u].r - tr[u].l + 1) * k; tr[u].add += k; } else{ pushdown(u); int mid = tr[u].l + tr[u].r >> 1; if(l <= mid) modify(u << 1, l, r, k); if(r > mid) modify(u << 1 | 1, l, r, k); pushup(u); } } int query(int u, int l, int r){ if(tr[u].l >= l && tr[u].r <= r){ //cout << tr[u].l << " " << tr[u].r << endl; return tr[u].sum; } else{ pushdown(u); int mid = tr[u].l + tr[u].r >> 1; int res = 0; if(l <= mid) res += query(u << 1, l, r); if(r > mid) res += query(u << 1 | 1, l, r); return res; } } signed main(void){ ios::sync_with_stdio(false); cin.tie(0); cin >> n >> m; for(int i = 1; i <= n; i++) cin >> w[i]; build(1, 1, n); for(int i = 1; i <= m; i++){ int op, l, r, k; cin >> op >> l >> r; if(op == 1){ cin >> k; modify(1, l, r, k); } else{ cout << query(1, l, r) << endl; } } return 0; }

__EOF__

本文作者ReSakura
本文链接https://www.cnblogs.com/ReSakura/p/16216304.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   ReSakura  阅读(37)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示