Tree Recovery 树状数组区间操作求和模板题

Tree Recovery

https://ac.nowcoder.com/acm/problem/15175

先对原数组a进行差分,得到差分数组b,才对b[i]和b[i]*i分别维护一个树状数组tb和tc,
而l到r的和变为[(r + 1) * sum(tb, r) - sum(tc, r)]-[(l + 1) * sum(tb, l) - sum(tc, l)]
需要注意的是开vector<>后靠resize()维护大小会卡在60%

#pragma GCC optimize(2)
#include <bits/stdc++.h>
#define endl  '\n'
#define ll long long
using namespace std;
ll a[100005],b[100005];//a为原数组,b为a的差分数组
ll tb[100005],tc[100005]; //b[i]和b[i]*i分别维护的一个树状数组
int n,m; //n为树状数组大小 
int lowbit(int x)
{
    return x&-x;
}
void add(int i,ll x)
{
    ll v=i*x;
    while(i<=n)
    {
        tb[i]+=x;
        tc[i]+=v;
        i+=lowbit(i);
    }
}
void range_add(int l,int r,ll x)
{
    add(l,x);
    add(r+1,-x);
}
ll sum_t(ll arr[],int i)
{
    ll res=0;
    while(i>0)
    {
        res+=arr[i];
        i-=lowbit(i);
    }
    return res;
}
ll sum(int i)
{
    return (i+1)*sum_t(tb,i)-sum_t(tc,i);
}
ll range_sum(int l,int r)
{
    return sum(r)-sum(l-1);
}

int main() {
    ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);
       cin>>n>>m;
       for(int i=1;i<=n;i++)
           cin>>a[i];
    for(int i=1;i<=n;i++)
           b[i]=a[i]-a[i-1];
    for(int i=1;i<=n;i++)
        add(i,b[i]);
    while(m--)
    {
        char c;cin>>c;
        if(c=='Q'){
            int x,y;cin>>x>>y;
            cout<<range_sum(x,y)<<endl;
        }
        else if(c=='C'){
            ll x,y,z;cin>>x>>y>>z;
            range_add(x,y,z);
        }
    }
    return 0;
}
全部评论

相关推荐

昨天 18:22
门头沟学院 运营
是正式编吗?稳定吗?工资待遇怎么样?转正可以转到腾讯总部吗?
Java抽象带篮子:不是,不稳定,一般,不行
投递腾讯云智研发等公司7个岗位 >
点赞 评论 收藏
分享
点赞 评论 收藏
分享
头顶尖尖的程序员:我也是面了三四次才放平心态的。准备好自我介绍,不一定要背熟,可以记事本写下来读。全程控制语速,所有问题都先思考几秒,不要急着答,不要打断面试官说话。
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
06-19 17:02
鼠鼠深知pdd的强度很大,但是现在没有大厂offer,只有一些不知名小厂我是拒绝等秋招呢,还是接下?求大家帮忙判断一下!
水中水之下水道的鼠鼠:接了再说,不图转正的话混个实习经历也不错
投递拼多多集团-PDD等公司10个岗位 >
点赞 评论 收藏
分享
评论
5
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务