P1438 无聊的数列
P1438 无聊的数列
题目描述
维护一个数列 ,支持两种操作:
-
1 l r K D
:给出一个长度等于 的等差数列,首项为 ,公差为 ,并将它对应加到 范围中的每一个数上。即:令 。 -
2 p
:询问序列的第 个数的值 。
输入格式
第一行两个整数数 表示数列长度和操作个数。
第二行 个整数,第 个数表示 。
接下来的 行,每行先输入一个整数 。
若 则再输入四个整数 ;
若 则再输入一个整数 。
输出格式
对于每个询问,一行一个整数表示答案。
样例 #1
样例输入 #1
5 2
1 2 3 4 5
1 2 4 1 2
2 3
样例输出 #1
6
提示
数据规模与约定
对于 数据,。
入手
在某个区间里对应加上一个等差数列。
查询第 个数的值。
假如一个序列是
0 0 0 0 0 0
在2-5
这个区间里加入首项为 2,公差为 5 的等差数列,数列变为
0 2 7 12 17 0
差分一下这个数组
0 2 5 5 5 -17
发现了吗?
我们在这个差分序列中的2处加入的首项,3-5处加入了相同的公差,6处加入了-(2+3*5)
所以我们维护一个差分序列的线段树,就在差分线段树上进行查询,每次要查询序列的第q个数,那么我们在线段树上的操作就是查询第 [1,q] 区间的和,我们要维护一个sum,和懒标记tag
代码如下:
#include <bits/stdc++.h>
using i64 = long long;
constexpr int N = 100010;
struct node {
int l, r;
i64 sum, tag;
} tr[N << 2];
int n, m;
int a[N], b[N];
void pushup(int u) {
tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
}
void pushdown(int u) {
int mid = (tr[u].l + tr[u].r) >> 1;
if (tr[u].tag) {
tr[u << 1].tag += tr[u].tag;
tr[u << 1].sum += tr[u].tag * (mid - tr[u].l + 1);
tr[u << 1 | 1].tag += tr[u].tag;
tr[u << 1 | 1].sum += tr[u].tag * (tr[u].r - mid);
tr[u].tag = 0;
}
}
void build(int u, int l, int r) {
if (l == r) {
tr[u] = {l, r, b[l], 0};
return;
}
tr[u] = {l, r};
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 x) {
if (l <= tr[u].l && r >= tr[u].r) {
tr[u].sum += (tr[u].r - tr[u].l + 1) * x;
tr[u].tag += x;
return;
}
pushdown(u);
int mid = (tr[u].l + tr[u].r) >> 1;
if (l <= mid) modify(u << 1, l, r, x);
if (r > mid) modify(u << 1 | 1, l, r, x);
pushup(u);
}
i64 query(int u, int l, int r) {
if (l <= tr[u].l && r >= tr[u].r) {
return tr[u].sum;
}
pushdown(u);
int mid = (tr[u].l + tr[u].r) >> 1;
i64 res = 0;
if (l <= mid) res += query(u << 1, l, r);
if (r > mid) res += query(u << 1 | 1, l, r);
pushup(u);
return res;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cin >> n >> m;
for (int i = 1; i <= n; i++ ) {
std::cin >> a[i];
b[i] = a[i] - a[i - 1];
}
build(1, 1, n);
while (m --) {
int op, l, r, k, d;
std::cin >> op >> l;
if (op == 1) {
std::cin >> r >> k >> d;
modify(1, l, l, k);
if (l + 1 <= r) modify(1, l + 1, r, d);
if (r < n) modify(1, r + 1, r + 1, -(k + d * (r - l)));
} else {
std::cout << query(1, 1, l) << '\n';
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探