两颗线段树,一颗用来统计每一次操作的次数,一颗就是寻常的统计求和的线段树。
学会了在结构体中构造多颗线段树的方法,因为建统计次数的线段树时,一直以n来建,导致wa了很多次。
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn 100005
struct Tree
{
int l,r;
__int64 num,lazy;
};
struct Command
{
int l,r;
__int64 d;
}Com[maxn<<1];
struct Segtree{
Tree tree[maxn<<2];
int nu[maxn<<1];
void PushUp(int rt)
{
tree[rt].num=tree[rt<<1].num+tree[rt<<1|1].num;
}
void PushDown(int rt)
{
if(tree[rt].lazy){
tree[rt<<1].num+=tree[rt].lazy*(tree[rt<<1].r-tree[rt<<1].l+1);
tree[rt<<1|1].num+=tree[rt].lazy*(tree[rt<<1|1].r-tree[rt<<1|1].l+1);
tree[rt<<1].lazy+=tree[rt].lazy;
tree[rt<<1|1].lazy+=tree[rt].lazy;
tree[rt].lazy=0;
}
}
void build(int l,int r,int rt)
{
tree[rt].l=l;
tree[rt].r=r;
tree[rt].lazy=0;
tree[rt].num=0;
if(l==r){
tree[rt].num=nu[l];
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
PushUp(rt);
}
void update(int x,int y,__int64 val,int rt)
{
int l,r;
l=tree[rt].l;
r=tree[rt].r;
if(l==x&&r==y){
tree[rt].lazy+=val;
tree[rt].num+=val*(tree[rt].r-tree[rt].l+1);
return ;
}
PushDown(rt);
int m=(l+r)>>1;
if(x<=m) update(x,min(y,m),val,rt<<1);
if(y>m) update(max(m+1,x),y,val,rt<<1|1);
PushUp(rt);
}
__int64 query(int pos,int rt)
{
int l,r;
l=tree[rt].l;
r=tree[rt].r;
if(l==r) return tree[rt].num;
PushDown(rt);
__int64 ans=0;
int m=(l+r)>>1;
if(pos<=m) return query(pos,rt<<1);
else return query(pos,rt<<1|1);
}
}a,b;
int main()
{
int i,k,n,m;
while(~scanf("%d%d%d",&n,&m,&k)){
for(i=1;i<=n;i++){
scanf("%d",&a.nu[i]);
}
memset(b.nu,0,sizeof(b.nu));
a.build(1,n,1);
b.build(1,m,1);
for(i=1;i<=m;i++){
scanf("%d%d%I64d",&Com[i].l,&Com[i].r,&Com[i].d);
}
int x,y;
for(i=1;i<=k;i++){
scanf("%d%d",&x,&y);
b.update(x,y,1,1);
}
for(i=1;i<=m;i++){
__int64 temp=b.query(i,1);
a.update(Com[i].l,Com[i].r,Com[i].d*temp,1);
}
for(i=1;i<=n;i++){
__int64 ans=a.query(i,1);
printf("%I64d ",ans);
}
printf("\n");
}
return 0;
}