【金色】种瓜得瓜,种豆得豆(线段树)

亮皇轻轻松松在大学四年间拿到了北理工rk0,也有很多家公司给他了offer,但是他看了看觉得薪水都太低了,并不想参加,于是决定回家种地。

他在家里开始种西瓜,家里一共有nn块瓜田,每年可以产出aiai个西瓜。每年亮皇回家的时候都会看看他种的这块地,他会做以下下两种操作之一:

  • 询问一段土地从第一年开始,到当年结束一共生产了多少个西瓜。
  • 在一段土地上种上黄豆,这样可以让这块西瓜地从下一年开始产量+1。

亮皇一共会回家mm年,请你帮他回答所有的查询。

Input

输入数据包括多组数据(不超过8组),请处理到文件结束。

对于每一组数据,第一行包括一个整数n(1≤n≤105)n(1≤n≤105),表示西瓜地的数量。

第二行包括nn个整数,表示初始年产量ai(ai≤105)ai(ai≤105)。

第三行包括mm个整数,表示亮皇要回家m(1≤m≤105)m(1≤m≤105)年。

接下来mm行,每行一定是以下两种形式之一:

  • "Q s t":查询第[s,t][s,t]块土地上从开始种地到当年结束的总产量。
  • "I s t":当年在第[s,t][s,t]块土地上种上黄豆。

数据保证至少有一次查询操作。

Output

对于每一组数据,在一行内回答所有的查询,用空格隔开。

Example

Input

4
1 1 1 1
3
Q 1 3
Q 1 4
Q 2 4
4
1 2 3 4
3
Q 1 4
I 1 3
Q 2 4

Output

3 8 9
10 29

建两颗线段树,一颗记录当前的年产量,另一颗记录多算的产量(每个点多算的产量为当前的年份),总产量 = 年产量×年份-多算的

#include<stdio.h>
#include<string.h>
#define lson num<<1
#define rson num<<1|1
#define mid  ((l+r)>>1)
long long  a[1200000],b[1200000],la[1200000],lb[1200000],flag,z[120000];
long long  ans1,ans2;

void down(long long  l,long long  r,long long  num)
{
    la[lson] += la[num];
    la[rson] += la[num];
    a[lson] += la[num]*(mid-l+1);
    a[rson] += la[num]*(r-mid);
    la[num] = 0;
}

void down1(long long  l,long long  r,long long  num)
{
    lb[lson] += lb[num];
    lb[rson] += lb[num];
    b[lson] += lb[num]*(mid-l+1);
    b[rson] += lb[num]*(r-mid);
    lb[num] = 0;
}

void build(long long  l, long long  r, long long  num)
{
    if(l == r)
    {
        scanf("%lld",&a[num]);
        return;
    }
    if(la[num] > 0)
        down(l,r,num);
    build(l,mid,lson);
    build(mid+1,r,rson);
    a[num] = a[lson] + a[rson];
}

void sum(long long  x, long long  y,long long  l, long long  r,long long  num)
{
    if(x<= l&&y >= r)
    {
        ans1 += a[num];
        return ;
    }
    if(la[num] > 0)
        down(l,r,num);
    if(x <= mid)
        sum(x,y,l,mid,lson);
    if(y > mid)
        sum(x,y,mid+1,r,rson);
}
void sum1(long long  x, long long  y,long long  l, long long  r,long long  num)
{
    if(x<= l&&y >= r)
    {
        ans2 += b[num];
        return ;
    }
    if(lb[num] > 0)
        down1(l,r,num);
    if(x <= mid)
        sum1(x,y,l,mid,lson);
    if(y > mid)
        sum1(x,y,mid+1,r,rson);
}

void plus(long long  x, long long  y,long long  l, long long  r, long long  num)
{
    if(l >= x&&r <= y)
    {
        la[num] += flag;
        a[num] += flag*(r-l+1);
        return;
    }
    if(la[num] > 0)
        down(l,r,num);
    if(x <= mid)
        plus(x,y,l,mid,lson);
    if(y > mid)
        plus(x,y,mid+1,r,rson);
    a[num] = a[lson] +a[rson];
}
void plus1(long long  x, long long  y,long long  l, long long  r, long long  num)
{
    if(l >= x&&r <= y)
    {
        lb[num] += flag;
        b[num] += flag*(r-l+1);
        return;
    }
    if(lb[num] > 0)
        down1(l,r,num);
    if(x <= mid)
        plus1(x,y,l,mid,lson);
    if(y > mid)
        plus1(x,y,mid+1,r,rson);
    b[num] = b[lson] + b[rson];
}

int main()
{
    long long  i,j,m,n,aa,bb,tail;
    char s[5];
    while(scanf("%lld",&n) !=EOF)
    {
        tail = -1;
        memset(b,0,sizeof(b));
        memset(la,0,sizeof(la));
        memset(lb,0,sizeof(lb));
        build(1,n,1);
        scanf("%lld",&m);
        for(i = 1; i <= m; i ++)
        {
            scanf("%s %lld %lld",s,&aa,&bb);
            if(s[0] == 'Q')
            {
                ans1 = ans2 = 0;
                sum(aa,bb,1,n,1) ;
                sum1(aa,bb,1,n,1);
                // prlong long f("%d\n",ans1*i-ans2);
                z[++tail] = ans1*i-ans2;
            }
            else
            {
                flag = 1;
                plus(aa,bb,1,n,1);
                flag = i;
                plus1(aa,bb,1,n,1);
            }
        }
        for(i = 0; i <= tail; i ++)
        {
            if(i == tail)
                printf("%lld\n",z[i]);
            else
                printf("%lld ",z[i]);
        }
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值