Codeforces Round #179 (Div. 2) C Greg and Array
2013-04-12 06:50
357 查看
C. Greg and Array
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
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.
Input
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.
Output
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 %I64dspecifier.
Sample test(s)
input
output
input
output
input
output
思路:这个题数据量很大。我用的方法是构造两个线段树来处理
首先要知道线段树的一个比较基本的模型,就是线段树成段的更新(一段+C或-C)
只要知道这个基本模型,题目可以分解为两不,第一步,利用x,y来构造线段树,判断每个操作出现了多少次
然后再把数组a
构造为一颗线段树,并且成段更新的时候,由于第一颗线段树已经可以知道当前这个操作执行了多少次,所以可以直接把di*c作为一个增加的量,来成段更新,这个di就是原来的增量,ci是通过第一颗线段树查找(i,i)这个区间出现的次数
最后把每一个ai都查找一次,就可以得到答案了。
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
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.
Input
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.
Output
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 %I64dspecifier.
Sample test(s)
input
3 3 3 1 2 3 1 2 1 1 3 2 2 3 4 1 2 1 3 2 3
output
9 18 17
input
1 1 1 1 1 1 1 1 1
output
2
input
4 3 6
1 2 3 4
1 2 1
2 3 23 4 4
1 21 3
2 3
1 21 3
2 3
output
5 18 31 20
思路:这个题数据量很大。我用的方法是构造两个线段树来处理
首先要知道线段树的一个比较基本的模型,就是线段树成段的更新(一段+C或-C)
只要知道这个基本模型,题目可以分解为两不,第一步,利用x,y来构造线段树,判断每个操作出现了多少次
然后再把数组a
构造为一颗线段树,并且成段更新的时候,由于第一颗线段树已经可以知道当前这个操作执行了多少次,所以可以直接把di*c作为一个增加的量,来成段更新,这个di就是原来的增量,ci是通过第一颗线段树查找(i,i)这个区间出现的次数
最后把每一个ai都查找一次,就可以得到答案了。
#include<stdio.h> #include<string.h> struct node { __int64 l; __int64 r; __int64 d; __int64 val; }; struct control { __int64 l; __int64 r; __int64 d; }; node tree1[400000]; node tree2[400000]; control con[100005]; __int64 num[100005],sum1,sum2; __int64 cnm[100005]; void build_tree1(__int64 l,__int64 r,__int64 root) { tree1[root].l=l; tree1[root].r=r; if(l==r) { tree1[root].val=0; tree1[root].d=0; return; } __int64 mid=(l+r)>>1; build_tree1(l,mid,root*2); build_tree1(mid+1,r,root*2+1); tree1[root].val=tree1[root*2].val+tree1[root*2+1].val; tree1[root].d=0; } void build_tree2(__int64 l,__int64 r,__int64 root) { tree2[root].l=l; tree2[root].r=r; if(l==r) { tree2[root].val=num[l]; tree2[root].d=0; return; } __int64 mid=(l+r)>>1; build_tree2(l,mid,root*2); build_tree2(mid+1,r,root*2+1); tree2[root].val=tree2[root*2].val+tree2[root*2+1].val; tree2[root].d=0; } void findsum1(__int64 l,__int64 r,__int64 root) { if(tree1[root].l==l&&tree1[root].r==r) { sum1=sum1+tree1[root].val; return; } sum1=sum1+(r-l+1)*tree1[root].d; __int64 mid=(tree1[root].l+tree1[root].r)>>1; if(mid>=r) findsum1(l,r,root*2); else if(mid<l) findsum1(l,r,root*2+1); else { findsum1(l,mid,root*2); findsum1(mid+1,r,root*2+1); } } void findsum2(__int64 l,__int64 r,__int64 root) { if(tree2[root].l==l&&tree2[root].r==r) { sum2=sum2+tree2[root].val; return; } sum2=sum2+(r-l+1)*tree2[root].d; __int64 mid=(tree2[root].l+tree2[root].r)>>1; if(mid>=r) findsum2(l,r,root*2); else if(mid<l) findsum2(l,r,root*2+1); else { findsum2(l,mid,root*2); findsum2(mid+1,r,root*2+1); } } void update1(__int64 l,__int64 r,__int64 c,__int64 root) { tree1[root].val=tree1[root].val+((r-l+1)*c); if(tree1[root].l==l&&tree1[root].r==r) { tree1[root].d=tree1[root].d+c; return; } __int64 mid=(tree1[root].l+tree1[root].r)>>1; if(mid>=r) update1(l,r,c,root*2); else if(mid<l) update1(l,r,c,root*2+1); else { update1(l,mid,c,root*2); update1(mid+1,r,c,root*2+1); } } void update2(__int64 l,__int64 r,__int64 c,__int64 root) { tree2[root].val=tree2[root].val+((r-l+1)*c); if(tree2[root].l==l&&tree2[root].r==r) { tree2[root].d=tree2[root].d+c; return; } __int64 mid=(tree2[root].l+tree2[root].r)>>1; if(mid>=r) update2(l,r,c,root*2); else if(mid<l) update2(l,r,c,root*2+1); else { update2(l,mid,c,root*2); update2(mid+1,r,c,root*2+1); } } int main() { __int64 i,n,a,b,c,m,k; while(scanf("%I64d%I64d%I64d",&n,&m,&k)!=EOF) { for(i=1;i<=n;i++) scanf("%I64d",&num[i]); build_tree1(1,m,1); for(i=1;i<=m;i++) { scanf("%I64d%I64d%I64d",&a,&b,&c); con[i].l=a; con[i].r=b; con[i].d=c; } for(i=1;i<=k;i++) { scanf("%I64d%I64d",&a,&b); update1(a,b,1,1); } for(i=1;i<=m;i++) { sum1=0; findsum1(i,i,1); cnm[i]=sum1; } build_tree2(1,n,1); for(i=1;i<=m;i++) update2(con[i].l,con[i].r,con[i].d*cnm[i],1); for(i=1;i<n;i++) { sum2=0; findsum2(i,i,1); printf("%I64d ",sum2); } sum2=0; findsum2(n,n,1); printf("%I64d\n",sum2); } return 0; }
相关文章推荐
- Codeforces Round #179 (Div. 1)-A. Greg and Array
- Codeforces Round#179(Div 2)C Greg and Array
- Codeforces Round #179 (Div. 1) A. Greg and Array
- Codeforces #179(Div 2)C Greg and Array
- CodeForces Round #179 (295A) - Greg and Array 一个线段树做两次用
- Codeforces Round #179 (Div. 2) B. Yaroslav and Two Strings
- Codeforces Round #374 (Div. 2) D. Maxim and Array 贪心
- Codeforces Round #312 (Div. 2)-B. Amr and The Large Array-暴力
- Codeforces Round #210 (Div. 2) C. Levko and Array Recovery
- Codeforces Round #251 (Div. 2) C. Devu and Partitioning of the Array
- 【Codeforces Round 331 (Div 2)B】【水题 贪心】Wilbur and Array 修改对p位置后的所有位置生效 最少修改次数使得数列变成b
- Codeforces Round #136 (Div. 1) B. Little Elephant and Array
- Codeforces Round #312 (Div. 2) B. Amr and The Large Array
- Codeforces Round #331 (Div. 2)-Wilbur and Array(贪心模拟)
- Codeforces Round 374 (Div 2)D Maxim and Array 【贪心】
- Codeforces Round #373 (Div. 2) E. Sasha and Array
- Codeforces Round #179 (Div. 2) B (codeforces 296b) Yaroslav and Two Strings
- Codeforces Round #249 (Div. 2)C Devu and Partitioning of the Array
- Codeforces Round #253 (Div. 2) E. Artem and Array (思维)
- Codeforces Round #249 (Div. 2)C Devu and Partitioning of the Array