作者:李慧颖yynd_613 | 来源:互联网 | 2024-12-09 15:16
本文详细探讨了一道涉及算法、C++及图论知识点的题目,适合对算法竞赛感兴趣的读者。通过分析题目【这是一道大水题】,我们将探索如何高效地处理区间查询与更新问题。本文由技术作者【ღCauchyོꦿ࿐】撰写,旨在帮助读者掌握相关技术和解题技巧。
本文将深入探讨一道算法题,该题目涉及到算法、C++以及图论等知识点。这道题目的名称是【这是一道大水题】,适合对算法竞赛感兴趣的朋友阅读。我们将会详细介绍题目的背景、输入输出要求、解题思路以及代码实现。
题目描述
本题出自2020-2021年度第二届全国大学生算法设计与编程挑战赛 F题。题目要求处理一系列区间更新和查询操作,具体如下:
输入
输入包含多组测试数据,每组数据的第一行包含两个整数 n 和 m (1 ≤ n, m ≤ 100,000),分别表示数组的长度和操作的数量。接下来 m 行,每行描述一个操作,操作类型有两种:
- 0 l r x:表示将区间 [l, r] 内的每个元素增加 x。
- 1 x:表示查询在不包含第 x 个元素的情况下,数组的总和。
输出
对于每个查询操作,输出一个整数,表示在不包含第 x 个元素的情况下,数组的总和。
样例输入
10 5
0 4 6 3
0 1 2 2
0 4 5 2
1 4
1 1
样例输出
4
13
解题思路
这道题的核心在于如何高效地处理区间更新和查询操作。直接对每个元素进行更新会导致时间复杂度过高,因此我们需要使用一种高效的数据结构来优化这一过程。
一个有效的解决方案是使用差分数组或线段树。差分数组可以在 O(1) 时间内完成区间更新,而在 O(n) 时间内完成一次查询。线段树则可以在 O(log n) 时间内完成区间更新和查询。
差分数组实现
#include
using namespace std;
const int N = 1e6 + 10;
int a[N];
void solve() {
int n, m; cin >> n >> m;
for (int i = 1; i <= m; i++) {
int op; cin >> op;
if (op == 0) {
int l, r, x; cin >> l >> r >> x;
a[l] += x;
a[r + 1] -= x;
} else {
int x; cin >> x;
int ans = 0;
for (int i = 1; i <= x; i++) ans += a[i];
cout < }
}
}
线段树实现
#include
using namespace std;
const int N = 2e6 + 10;
const int mod = 1e9 + 7;
const int inf = 1e9;
struct node {
int l, r;
int val, lz;
} tr[N * 2];
void pushup(int u) {
tr[u].val = tr[u <<1].val + tr[u <<1 | 1].val;
}
void pushdown(int u) {
if (tr[u].lz) {
tr[u <<1].val += tr[u].lz * (tr[u <<1].r - tr[u <<1].l + 1);
tr[u <<1 | 1].val += tr[u].lz * (tr[u <<1 | 1].r - tr[u <<1 | 1].l + 1);
tr[u <<1].lz += tr[u].lz;
tr[u <<1 | 1].lz += tr[u].lz;
tr[u].lz = 0;
}
}
void build(int u, int l, int r) {
tr[u].l = l, tr[u].r = r;
if (l == r) return;
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 (tr[u].l >= l && tr[u].r <= r) {
tr[u].val += (tr[u].r - tr[u].l + 1) * x;
tr[u].lz += 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);
}
int query(int u, int l, int r) {
if (tr[u].l >= l && tr[u].r <= r) return tr[u].val;
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
int ans = 0;
if (l <= mid) ans += query(u <<1, l, r);
if (r > mid) ans += query(u <<1 | 1, l, r);
return ans;
}
void solve() {
int n, m; cin >> n >> m;
build(1, 1, n);
int ans = 0;
for (int i = 1; i <= m; i++) {
int op; cin >> op;
if (op == 0) {
int l, r, x; cin >> l >> r >> x;
ans += (r - l + 1) * x;
modify(1, l, r, (r - l + 1) * x);
} else {
int x; cin >> x;
cout < }
}
}
本文《深入解析一道算法题》版权归【ღCauchyོꦿ࿐】所有,引用需遵循CC 4.0 BY-SA版权协议。