思路:这个题数据量很大。我用的方法是构造两个线段树来处理
首先要知道线段树的一个比较基本的模型,就是线段树成段的更新(一段+C或-C)
只要知道这个基本模型,题目可以分解为两不,第一步,利用x,y来构造线段树,判断每个操作出现了多少次
然后再把数组a[n]构造为一颗线段树,并且成段更新的时候,由于第一颗线段树已经可以知道当前这个操作执行了多少次,所以可以直接把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;
}