Codeforces Round #179 (Div. 2) C. Greg and Array

                                                                                                                      Greg and Array
                                                                                                         time limit per test   2 seconds
                                                                                                   memory limit per test  56 megabytes
                                                                                                                 input   standard input
                                                                                                                  output   standard output

Greg has an array a = a1, a2, ..., an andm operations. Each operation looks as: li,ri,di,(1 ≤ li ≤ ri ≤ n). To apply operationi to the array means to increase all array elements with numbersli, li + 1, ..., ri by valuedi.

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 numbersxi, 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 containsn integers:a1, a2, ..., an(0 ≤ ai ≤ 105) — the initial array.

Next m lines contain operations, the operation numberi is written as three integers:li,ri,di,(1 ≤ li ≤ ri ≤ n),(0 ≤ di ≤ 105).

Next k lines contain the queries, the query numberi 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 inC++. It is preferred to use thecin, cout streams of the%I64d specifier.

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 2
3 4 4
1 2
1 3
2 3
1 2
1 3
2 3
Output
5 18 31 20
   这题真是太遗憾了,有一个地方下标应该从1开始写成了0,结果浪费了5分多钟的时间找bug,结果比赛就结束了,遗憾啊。
   考察点:树状数组
   思路:建立两个树状数组,分别统计操作实行的次数和每次操作数值的变化
#include <stdio.h>
#include <string.h>
#include <math.h>
__int64 tree1[110000],tree2[110000];
struct num
{
    int l,r,val;
}a[110000];
__int64 b[1000000],sum[110000];
__int64 n,m;
int main()
{
    void build(__int64 k,__int64 val);
    void build2(__int64 k,__int64 val);
    __int64 search(__int64 k);
     __int64 search2(__int64 k);
    __int64 i,j,s,t;
    __int64 x,y,k;
    while(scanf("%I64d %I64d %I64d",&n,&m,&k)!=EOF)
    {
       for(i=1;i<=n;i++)
       {
           scanf("%I64d",&b[i]);
       }
       for(i=1;i<=m;i++)
       {
           scanf("%d %d %d",&a[i].l,&a[i].r,&a[i].val);
       }
       memset(tree2,0,sizeof(tree2));
       memset(tree1,0,sizeof(tree1));
       for(i=1;i<=k;i++)
       {
           scanf("%I64d %I64d",&x,&y);
           build(y,1);
           build(x-1,-1);
       }
       memset(sum,0,sizeof(sum));
       for(i=1;i<=m;i++)
       {
           t=search(i);
           sum[i]=sum[i]+t;
       }
       for(i=1;i<=m;i++)
       {
           build2(a[i].r,sum[i]*a[i].val);
           build2(a[i].l-1,-1*sum[i]*a[i].val);
       }
       for(i=1;i<=n;i++)
       {
           t=search2(i);
           b[i]+=t;
           if(i==1)
           {
               printf("%I64d",b[i]);
           }else
           {
               printf(" %I64d",b[i]);
           }
       }
       printf("\n");
    }
    return 0;
}
int f(int k)
{
    return (k&-k);
}
void build(__int64 k,__int64 val)
{
    while(k>0)
    {
        tree2[k]+=val;
        k-=f(k);
    }
}
__int64 search(__int64 k)
{
    __int64 s=0;
    while(k<=m)
    {
        s+=tree2[k];
        k+=f(k);
    }
    return s;
}
void build2(__int64 k,__int64 val)
{
    while(k>0)
    {
        tree1[k]+=val;
        k-=f(k);
    }
}
__int64 search2(__int64 k)
{
    __int64 s=0;
    while(k<=n)
    {
        s+=tree1[k];
        k+=f(k);
    }
    return s;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值