📅  最后修改于: 2023-12-03 15:42:22.334000             🧑  作者: Mango
本题是一个模拟题,考察对数组和逻辑的掌握。
一个长度为 $N$ 的序列,开始时所有元素都为 0。现在有 $M$ 次操作,每次操作将区间 $[L, R]$ 内的数全部加上 $C$。请你求出进行完所有操作后,整个序列中有多少元素大于等于 $T$。
第一行输入三个数字 $N$, $M$, $T$。 接下来 $M$ 行,每行 $3$ 个数字 $L$, $R$, $C$。
一个数字表示大于等于 $T$ 的元素个数。
5 3 3
1 3 2
2 4 1
3 5 3
2
我们可以使用标记永久化 LazyTag 的方法来维护区间加操作。即对于每个节点,需要记录其区间加的懒标记,每次查询时,将懒标记向下传递,最终得到每个节点的值。
具体实现上,采用分治的思想,将原序列划分为若干个区间,然后对于每个区间记录其对应的节点。对于每个节点,我们需要记录其值和懒标记。值表示该区间内所有元素的和,懒标记表示该区间内所有元素需要加上的值。
在进行区间加操作时,我们需要将操作作用于查询区间的节点,并将懒标记标记为需要加上的值。在查询时,将懒标记传递到下层节点,然后根据查询的区间,将目标区间按中点进行划分,递归向下查询,并将查询结果做合并。
#include <stdio.h>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 500010;
int n, m, T;
int w[N], son[N][2];
int idx;
struct Node
{
int l, r;
int sum, add;
} tr[N * 40];
int build(int l, int r)
{
int u = ++idx;
if (l == r) tr[u] = {l, r, w[l], 0};
else
{
int mid = l + r >> 1;
son[u][0] = build(l, mid), son[u][1] = build(mid + 1, r);
tr[u] = {l, r, tr[son[u][0]].sum + tr[son[u][1]].sum, 0};
}
return u;
}
int modify(int u, int l, int r, int c)
{
int p = ++idx;
tr[p] = tr[u];
tr[p].add += c;
tr[p].sum += (min(r, tr[p].r) - max(l, tr[p].l) + 1) * c;
if (tr[p].l >= l && tr[p].r <= r) return p;
int mid = tr[p].l + tr[p].r >> 1;
if (l <= mid) son[p][0] = modify(son[u][0], l, r, c);
else son[p][0] = son[u][0];
if (r > mid) son[p][1] = modify(son[u][1], l, r, c);
else son[p][1] = son[u][1];
tr[p].sum = tr[son[p][0]].sum + tr[son[p][1]].sum + (tr[p].r - tr[p].l + 1) * tr[p].add;
return p;
}
int query(int u, int l, int r)
{
if (l <= tr[u].l && r >= tr[u].r) return tr[u].sum;
int mid = tr[u].l + tr[u].r >> 1;
int sum = 0;
if (l <= mid) sum += query(son[u][0], l, r);
if (r > mid) sum += query(son[u][1], l, r);
return sum + (min(r, tr[u].r) - max(l, tr[u].l) + 1) * tr[u].add;
}
int main()
{
scanf("%d%d%d", &n, &m, &T);
for (int i = 1; i <= n; i++) scanf("%d", &w[i]);
build(1, n);
while (m--)
{
int l, r, c;
scanf("%d%d%d", &l, &r, &c);
modify(1, l, r, c);
}
int ans = 0;
for (int i = 1; i <= n; i++) ans += query(1, i, i) >= T;
printf("%d\n", ans);
return 0;
}
时间复杂度$O(m\log n)$。