POJ 3468 树状数组区间修改+区间查询

题目传送门

对于区间修改+单点查询,我们是用差分的思想去完成,一直维护一个差分数组,到时候查询的时候差分的前缀和就行了。

那么对于区间查询,我们不可能对区间中每一个点都去查询,然后相加,这样时间复杂度过不去,于是,我们就要想更加好的方法。

我们要对一个区间求和,即a1+a2+a3+…+an,即对差分数组d1+d1+d2+d1+d2+d3+…+d1+d2+…+dn,也就是nd1+(n-1)d2+…+dn;那么我们只要用另一个数组维护一下di*(i-1)就行,到时候输出区间和的时候,就对这个数组求和即可。

#include<iostream>
using namespace std;
const int N=1e5+5;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const double EPS=1e-6;
typedef long long ll;
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define int long long
int a[N],d[N],sum1[N],sum2[N];
int n,q;
int lowbit(int x)
{
    return x&-x;
}
void add(int x,int k)
{
    for(int i=x;i<=n;i+=lowbit(i))
    {
        sum1[i]+=k;
        sum2[i]+=k*(x-1);
    }
}
int sum(int x)
{
    int s=0;
    for(int i=x;i;i-=lowbit(i))
    {
        s+=x*sum1[i]-sum2[i];
    }
    return s;
}
signed main()
{
    IOS;
    //freopen("","r",stdin);
    //freopen("","w",stdout);
    cin>>n>>q;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        d[i]=a[i]-a[i-1];
        add(i,d[i]);
    }
    while(q--)
    {
        char ch;
        cin>>ch;
        if(ch=='Q')
        {
            int x,y;
            cin>>x>>y;
            cout<<sum(y)-sum(x-1)<<endl;
        }
        else
        {
            int x,y,k;
            cin>>x>>y>>k;
            add(x,k);
            add(y+1,-k);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值