bzoj 3212

来源:互联网 发布:易语言安装包源码 编辑:程序博客网 时间:2024/06/06 05:45

题意:给你一个数列,给出2种操作 1.a b x [a,b]内的数加上x  2.a,b 询问 [a,b] 内所有数的和



分析:线段树区间修改,区间查询。(貌似用树状数组写有一个很长的公式)



技能:无



代码:

#include<bits/stdc++.h>
using namespace std;

#define ll long long
#define rep(i,a,b) for (ll i=a;i<=b;++i)
#define N 100010

ll val[N<<2],sum[N<<2],n,m;

ll read()
{
    ll x=0,f=1; char ch=getchar();
    for (;ch>'9' || ch<'0';ch=getchar()) if (ch=='-') f=-1;
    for (;ch>='0' && ch<='9';ch=getchar()) x=x*10+ch-'0';
    return x*f;
}

void pushdown(ll root,ll len)
{
    if (val[root])
    {
        val[root<<1]+=val[root];
        val[root<<1|1]+=val[root];
        sum[root<<1]+=val[root]*(len-(len>>1));
        sum[root<<1|1]+=val[root]*(len>>1);
        val[root]=0;
    }
}

void pushup(ll root)
{
    sum[root]=sum[root<<1]+sum[root<<1|1];
}

void add(ll root,ll l,ll r,ll L,ll R,ll y)
{
    if (L<=l&&r<=R)
    {
        sum[root]+=(r-l+1)*y;
        val[root]+=y;
        return;
    }
    pushdown(root,r-l+1);
    ll mid=l+r>>1;
    if (L<=mid) add(root<<1,l,mid,L,R,y);
    if (mid<R) add(root<<1|1,mid+1,r,L,R,y);
    pushup(root);
}

ll query(ll root,ll l,ll r,ll L,ll R)
{
    if (L<=l&&r<=R) return sum[root];
    pushdown(root,r-l+1);
    ll mid=l+r>>1,ans=0;
    if (L<=mid) ans+=query(root<<1,l,mid,L,R);
    if (mid<R) ans+=query(root<<1|1,mid+1,r,L,R);
    return ans;
}

int main()
{
    n=read(); m=read();
    rep(i,1,n)
    {
        ll x=read();
        add(1,1,n,i,i,x);
    }
    char ch[5];
    rep(i,1,m)
    {
        scanf("%s",ch);
        if (ch[0]=='Q')
        {
            ll x=read(),y=read(); printf("%lld\n",query(1,1,n,x,y));
        }
        else
        {
            ll x=read(),y=read(),v=read(); add(1,1,n,x,y,v);
        }
    }
    return 0;
}

原创粉丝点击