Impossible Boss+SPOJ+线段树区间更新、区间查询

 Impossible Boss

Problem code: DCEPC11I


Vaibhav Sir and Saikat Sir, after completing their graduation, got a job together at a store.

Their boss at the store was Sidharth Sir, who was very strict and did not want anyone to have fun at the job. He gave Vaibhav and Saikat sir a very boring job of stacking columns of boxes in a row of size N.

To make it a little interesting, both of them decided that whenever they need to add more boxes, they will choose st and en, such that 1<=st<=en<=N, and place 1 box in column st, 2 boxes in column st+1, … and (en-st+1) boxes in column en.

When Sidharth sir saw this, he decided to have some fun of his own, and asked them to count the number of boxes in all columns from st to en, and tell him the result. Now Vaibhav and Saikat sir have come to you for help to answer the queries of their boss, as they do not want to lose their jobs.

Input

The first line contains N, the number of columns and Q, the number of queries.

The next Q lines can be of the following form –

1)      0 st en, meaning Vaibhav and Saikat sir add boxes to the columns from st to en as described above.

2)      1 st en, meaning Sidharth sir asks them to count the number of boxes in all columns from st to en.

Output

For all queries of type 2, output a line containing the answer to the query.

Example

Input:
5 6
0 2 4
1 1 5
0 1 5
0 3 5
1 1 5
1 3 5

Output:
6
27
23

Constraints:

1<=N, Q<=100000

 
解决方案:此题并不是对区间加一个数,而是对区间加一个等差数列的操作,这个就有点难搞了,当时都没想法,看了解题报告才知,原来可以维护区间的首项、公差即可以了,更新或查询的是时候,把标记传下去就可以了。
code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MMAX 100003
#define lson L,M,rt<<1
#define rson M+1,R,rt<<1|1
using namespace std;
long long sum[MMAX<<2];///区间和
long long a[MMAX<<2];///维护首项
long long d[MMAX<<2];///维护等差
int N,Q;
long long _sum;
void push_up(int rt)
{
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void push_down(int rt,long long lenl,long long lenr)
{
    if(d[rt]||a[rt])
    {
        long long a1=a[rt],a2=a[rt]+(lenl)*d[rt];
        sum[rt<<1]+=a1*lenl+((lenl-1)*lenl)*d[rt]/2;
        sum[rt<<1|1]+=a2*lenr+lenr*(lenr-1)*d[rt]/2;
        d[rt<<1]+=d[rt],a[rt<<1]+=a1;
        d[rt<<1|1]+=d[rt],a[rt<<1|1]+=a2;
        d[rt]=0,a[rt]=0;
    }

}
void update(int L,int R,int rt,int sl,int sr)
{

    if(sl<=L&&sr>=R)
    {
        long long al=L-sl+1,len=R-L+1;
        sum[rt]+=al*len+(len-1)*len/2;
        a[rt]+=al,d[rt]++;
    }
    else
    {
        int M=(L+R)>>1;
        push_down(rt,M-L+1,R-M);
        if(sl<=M) update(lson,sl,sr);
        if(sr>M) update(rson,sl,sr);
        push_up(rt);
    }

}
void query(int L,int R,int rt,int ql,int qr)
{

    if(ql<=L&&qr>=R)
    {
        _sum+=sum[rt];
    }
    else
    {
        int M=(L+R)>>1;
        push_down(rt,M-L+1,R-M);
        if(ql<=M) query(lson,ql,qr);
        if(qr>M) query(rson,ql,qr);

    }

}
int main()
{
    while(~scanf("%d%d",&N,&Q))
    {
        memset(d,0,sizeof(d));
        memset(a,0,sizeof(a));
        memset(sum,0,sizeof(sum));
        for(int i=0; i<Q; i++)
        {
            _sum=0;
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            if(a)
            {
                query(1,N,1,b,c);
                printf("%lld\n",_sum);

            }
            else update(1,N,1,b,c);
        }


    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值