CodeForces 296C Greg and Array (線段樹)
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: x
Now Greg is wondering, what the array a will be after all the queries are executed. Help Greg.
Input
The first line contains integers n, m, k (1 ≤ n, m, k ≤ 105).
The second line contains n
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.
OutputOn 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 %I64dspecifier.
Sample test(s) input3 3 3 1 2 3 1 2 1 1 3 2 2 3 4 1 2 1 3 2 3output
9 18 17input
1 1 1 1 1 1 1 1 1output
2input
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 3output
5 18 31 20
題意:長度為n的序列;m種操作:a b c表示第a~b個數的值加上c;k次執行:a b表示執行第a~b種操作。最後輸出執行完所有操作後的數列。
先用線段樹計算出每種操作執行的次數,將操作中要加的數乘以次數更新。再用線段樹求出每個位置的數需要加的最終數值。感覺兩個都是簡單線段樹,就習慣性套模板,而且兩個線段樹又是先後分開執行,所以寫了一個線段樹就夠了。
#include <cstdio>
#include <iostream>
#include <algorithm>
#define ls node << 1
#define rs node << 1 | 1
#define lson l,mid,ls
#define rson mid + 1,r,rs
#define maxn 100005
using namespace std;
long long a[maxn];
int n,m,k,x,y;
long long cnt[maxn];
struct Operation {
int l;
int r;
long long d;
} o[maxn];
struct Query {
int l;
int r;
long long c;
long long num;
} q[maxn << 2];
void build(int l, int r, int node)
{
q[node].l = l;
q[node].r = r;
q[node].num = 0;
q[node].c = 0;
if(l == r)
return;
int mid = (l + r) >> 1;
build(lson);
build(rson);
}
void pushdown(int node,int len)
{
if(q[node].c) {
q[ls].c += q[node].c;
q[rs].c += q[node].c;
q[ls].num += q[node].c * (len - (len >> 1));
q[rs].num += q[node].c * (len >> 1);
q[node].c = 0;
}
}
void update(int x,int y,long long c,int l,int r,int node)
{
if(x <= l && y >= r) {
q[node].c += c;
q[node].num += c * (r - l + 1);
return;
}
pushdown(node, r - l + 1);
int mid = (l + r) >> 1;
if(x <= mid)
update(x,y,c,lson);
if(y > mid)
update(x,y,c,rson);
}
long long findnum(int x, int l, int r, int node)
{
if(x == l && x == r)
return q[node].num;
pushdown(node,r - l + 1);
int mid = (l + r) >> 1;
if(x > mid)
return findnum(x,rson);
if(x <= mid)
return findnum(x,lson);
}
int main()
{
//freopen("in.txt","r",stdin);
while(scanf("%d%d%d",&n,&m,&k) != EOF) {
for(long long i = 1; i <= n; i++)
scanf("%lld",&a[i]);
for(long long i = 1; i <= m; i++)
scanf("%d%d%lld",&o[i].l,&o[i].r,&o[i].d);
build(1,m,1);
for(long long i = 1; i <= k; i++) {
scanf("%d%d",&x,&y);
update(x,y,1,1,m,1);
}
for(int i = 1; i <= m; i++) {
cnt[i] = findnum(i,1,m,1);
//cout << cnt[i] << endl;
o[i].d *= cnt[i];
}
build(1,n,1);
for(int i = 1; i <= m; i++)
update(o[i].l,o[i].r,o[i].d,1,n,1);
for(int i = 1; i < n; i++)
printf("%lld ",a[i] + findnum(i,1,n,1));
printf("%lld\n",a[n] + findnum(n,1,n,1));
}
}