树状数组——区间修改,区间查询练习

http://codevs.cn/problem/1082/

板子题,注意范围,会爆int

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 5;

ll a[N], d[N], s1[N], s2[N];
int n, qr;

int lowbit(int k)
{
    return k & -k;
}

void add(ll * c, int p,ll v)
{
    while(p <= n)
    {
        c[p] += v;
        p += lowbit(p);
    }
}

ll sigma(ll *c,int p)
{
    ll r = 0;
    while(p > 0)
    {
        r += c[p];
        p -= lowbit(p);
    }
    return r;
}

void update(int s,int e,ll v)
{
    add(s1, s, v);
    add(s1, e + 1, -v);
    add(s2, s, v * (s-1));
    add(s2, e + 1, (-v) * e);
}

ll getSum(int l,int r)
{
    ll ans1 = (l - 1) * sigma(s1, l - 1) - sigma(s2, l - 1);
    ll ans2 = r * sigma(s1, r) - sigma(s2, r);

    return ans2 - ans1;
}
int main()
{
    int t;
    scanf("%d",&n);
    for(int i = 1;i <= n;i ++)
    {
        scanf("%d",&a[i]);
        d[i] = a[i] - a[i - 1];
    }

    for(int i = 1;i <= n;i ++)
    {
        add(s1, i, d[i]);
        add(s2, i, (i - 1)*d[i]);
    }

    scanf("%d",&qr);

    int h, l, r, v;
    for(int i = 1;i <= qr;i ++)
    {
        scanf("%d",&h);
        if(h == 1)
        {
            scanf("%d%d%d",&l,&r,&v);
            update(l,r,v);
        }
        else
        {
            scanf("%d%d",&l,&r);
            cout << getSum(l,r) << '\n';
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Soul_97/article/details/81531629