传送门:点击打开链接
Greg has an array a = a1, a2, ..., an and m operations. Each operation looks as: li, ri, di, (1 ≤ li ≤ ri ≤ n). To apply operation i to the array means to increase all array elements with numbers li, li + 1, ..., ri by value di.
Greg wrote down k queries on a piece of paper. Each query has the following form: xi, yi, (1 ≤ xi ≤ yi ≤ m). That means that one should apply operations with numbers xi, xi + 1, ..., yi to the array.
Now Greg is wondering, what the array a will be after all the queries are executed. Help Greg.
The first line contains integers n, m, k (1 ≤ n, m, k ≤ 105). The second line contains n integers: a1, a2, ..., an (0 ≤ ai ≤ 105) — the initial array.
Next m lines contain operations, the operation number i is written as three integers: li, ri, di, (1 ≤ li ≤ ri ≤ n), (0 ≤ di ≤ 105).
Next k lines contain the queries, the query number i is written as two integers: xi, yi, (1 ≤ xi ≤ yi ≤ m).
The numbers in the lines are separated by single spaces.
On a single line print n integers a1, a2, ..., an — the array after executing all the queries. Separate the printed numbers by spaces.
Please, do not use the %lld specifier to read or write 64-bit integers in C++. It is preferred to use the cin, cout streams of the %I64d specifier.
3 3 3 1 2 3 1 2 1 1 3 2 2 3 4 1 2 1 3 2 3
9 18 17
1 1 1 1 1 1 1 1 1
2
4 3 6 1 2 3 4 1 2 1 2 3 2 3 4 4 1 2 1 3 2 3 1 2 1 3 2 3
5 18 31 20
题意:给出一个数列,长度为n,m个操作,k个对操作的执行。对于每一个操作,将数列的区间[Li,Ri]都加上Di。对于每一个执行,对操作[Xi,Yi]都执行一次。最后输出所有执行之后,这个数列的每一个元素的值。
思路:计算出每一个操作执行的次数,也就是每一个操作总共会累加多少值,在对数列进行区间累加即可。要算出每个操作执行了多少次,可以用线段树对操作的下标进行建树,对于每一个执行,对这个线段树进行区间累加1的操作。这样就能算出每个操作执行了多少次,也就可以算出,每个操作最后累加了多少。最后再用另一个线段树维护数列即可
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#define LL long long
using namespace std;
struct node
{
int l, r;
LL add;
}tree[400005];
void pushdown(int id)
{
if (tree[id].add)
{
tree[id << 1].add += tree[id].add;
tree[id << 1 | 1].add += tree[id].add;
tree[id].add = 0;
}
}
void build(int id, int l, int r)
{
tree[id].l = l;
tree[id].r = r;
tree[id].add = 0;
if (l != r)
{
int mid = (l + r) >> 1;
build(id << 1, l, mid);
build(id << 1 | 1, mid + 1, r);
}
}
void op(int id, int l, int r, LL add)
{
if (l <= tree[id].l&&tree[id].r <= r)
{
tree[id].add += add;
}
else
{
pushdown(id);
int mid = (tree[id].l + tree[id].r) >> 1;
if (l <= mid) op(id << 1, l, r, add);
if (mid<r) op(id << 1 | 1, l, r, add);
}
}
int a[100005];
int b[100005];
struct operate
{
int l, r;
LL add;
}OP[100005];
void out(int id)
{
if (tree[id].l == tree[id].r)
{
b[tree[id].l] = tree[id].add;
}
else
{
pushdown(id);
out(id << 1);
out(id << 1 | 1);
}
}
void out2(int id)
{
if (tree[id].l == tree[id].r)
{
printf("%I64d ", a[tree[id].l] + tree[id].add);
}
else
{
pushdown(id);
out2(id << 1);
out2(id << 1 | 1);
}
}
int main()
{
int n, m, k;
scanf("%d %d %d", &n, &m, &k);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
build(1, 1, m);
for (int i = 1; i <= m; i++)
{
scanf("%d %d %I64d", &OP[i].l, &OP[i].r, &OP[i].add);
}
while (k--)
{
int x, y;
scanf("%d %d", &x, &y);
op(1, x, y, 1);
}
out(1);
build(1, 1, n);
for (int i = 1; i <= m; i++)
{
if (!b[i]) continue;
op(1, OP[i].l, OP[i].r, OP[i].add*b[i]);
}
out2(1);
return 0;
}