A Simple Problem with Integers---一个简单的整数问题

http://poj.org/problem?id=3468

 

You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.

Input

The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
"C a b c" means adding c to each of AaAa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of AaAa+1, ... , Ab.

Output

You need to answer all Q commands in order. One answer in a line.

Sample Input

10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4

Sample Output

4
55
9
15

Hint

The sums may exceed the range of 32-bit integers.

 题意:

给定Q (1 ≤ Q ≤ 100,000)个数A1,A2 … AQ,,
以及可能多次进行的两个操作:
1) 对某个区间Ai … Aj的每个数都加n(n可变)
2) 求某个区间Ai … Aj的数的和

 讲解线段树~

思路:用线段树,注意返回值用long long,开的数组是所给范围的4倍

Code:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
char str[10];
long long int lazy[400040],sum[400040];///4倍的空间
void build(int l,int r,int o)///建树  l,r 此节点区间长度    o下标
{
    if(l==r)///叶节点
    {
        scanf("%lld",&sum[o]);///直接赋值
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,o<<1);///左
    build(mid+1,r,o<<1|1);///右
    sum[o]=sum[o<<1]+sum[o<<1|1];///更新此节点的和
}
void pushdown(int o,int l)///o下标   l此节点的区间长度
{
    if(lazy[o])///如果此时需要更新操作
    {
        lazy[o<<1]+=lazy[o];///左
        lazy[o<<1|1]+=lazy[o];///右
        sum[o<<1]+=lazy[o]*(l-(l>>1));///更新此时  左   的和
        sum[o<<1|1]+=lazy[o]*(l>>1);///更新此时  右   的和
        lazy[o]=0;///此点位置懒惰标记取消    传到下面两个节点
    }
}
void update(int x,int y,int l,int r,int o,int c)///update(l,r,1,n,1,c);
{///x,y操作区间       l,r树的范围     o下标    c具体操作(+c)
    if(x<=l&&y>=r)///操作区间全在树的范围内
    {
        sum[o]+=(r-l+1)*c;///对此时sum[o]进行更新操作
        lazy[o]+=c;///并懒惰标记
        return ;
    }
    pushdown(o,r-l+1);///不符合  就push懒惰标记
    int mid=(l+r)>>1;
    if(x<=mid)update(x,y,l,mid,o<<1,c);///更新左
    if(y>mid)update(x,y,mid+1,r,o<<1|1,c);///更新右
    sum[o]=sum[o<<1]+sum[o<<1|1];///更新此节点的和
}
long long int query(int x,int y,int l,int r,int o)
{///x,y操作区间       l,r树的范围     o下标
    if(x<=l&&y>=r)///全包含   就输出此时区间的和
        return sum[o];
    pushdown(o,r-l+1);///懒惰标记函数
    int mid=(r+l)>>1;
    long long sum=0;///long long型
    if(x<=mid)sum+=query(x,y,l,mid,o<<1);///说明  树的左边与操作区间有交集
    if(y>mid)sum+=query(x,y,mid+1,r,o<<1|1);///o<<1|1   位运算比+-快
    return sum;
}
int main()
{
    int n,m;
    while(~scanf("%d %d",&n,&m))
    {
        memset(lazy,0,sizeof(lazy));
        memset(sum,0,sizeof(sum));
        build(1,n,1);///建树
        while(m--)
        {
            int l,r,c;
            scanf("%s",&str);///字符串避免回车符
            if(str[0]=='Q')
            {
                scanf("%d %d",&l,&r);
                printf("%lld\n",query(l,r,1,n,1));///查询函数
            }
            else
            {
                scanf("%d %d %d",&l,&r,&c);
                update(l,r,1,n,1,c);///操作更新函数
            }
        }
    }
    return 0;
}

 

 压力就是比你优秀百倍的人比你还在努力!~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵩韵儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值