UOJ Logo SHYI的博客

博客

Pku3468 A Simple Problem with Integers 题解

2016-07-21 20:09:18 By SHYI

题目大意:一个数列,有两个操作:1.修改操作,将一段区间内的数加上c;2.查询操作,查询一段区间内的数的和。

思路:线段树裸题,区间修改、区间查询,维护和以及加上的数,由于无序,不需要向下推标记,只需在子树更新完之后更新根节点即可。

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;

long long sum[400001],mor[400001];

void up(int cur,int t)
{
    sum[cur]=sum[cur<<1]+sum[cur<<1|1]+t*mor[cur];
}

void add(int L,int R,int l,int r,int x,int cur)
{
    if (L>=l && R<=r)
    {
        mor[cur]+=x;
        sum[cur]+=(R-L+1)*x;
        return;
    }
    int mid=L+R>>1;
    if (l<=mid) add(L,mid,l,r,x,cur<<1);
    if (r>mid) add(mid+1,R,l,r,x,cur<<1|1);
    up(cur,R-L+1);
}

long long ask(int L,int R,int l,int r,int cur)
{
    if (L>=l && R<=r) return sum[cur];
    int mid=L+R>>1;
    long long ans=mor[cur]*(r-l+1);
    if (l<=mid) ans+=ask(L,mid,l,min(mid,r),cur<<1);
    if (r>mid) ans+=ask(mid+1,R,max(l,mid+1),r,cur<<1|1);
    return ans;
}

int main()
{
    int n,m,i,a,b,c;
    scanf("%d%d",&n,&m);
    for (i=1;i<=n;i++) scanf("%d",&a),add(1,n,i,i,a,1);
    for (i=1;i<=m;i++)
    {
        char ch=getchar();
        while (ch<'A' || ch>'Z') ch=getchar();
        if (ch=='Q') scanf("%d%d",&a,&b),printf("%lld\n",ask(1,n,a,b,1));
        else scanf("%d%d%d",&a,&b,&c),add(1,n,a,b,c,1);
    }
    return 0;
}

评论

暂无评论

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。