0
点赞
收藏
分享

微信扫一扫

树状数组 1/30

8052cf60ff5c 2022-01-31 阅读 52
算法

树状数组分为三大类:
1.单点修改+区间求和
2.区间修改+单点求和(运用工具差分数组)
3.区间修改+区间求和(维护两个数组的前缀和)

典型的差分思想:
https://www.luogu.com.cn/problem/P3655

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int maxn=2e5+5;
ll N,S,Q,T,c[maxn],ls;
ll ans;
inline ll cc(ll x)
{
    if(x>0)
        return -S*x;
    return -T*x;
}
int main()
{
    scanf("%lld%lld%lld%lld",&N,&Q,&S,&T);
    for(register ll i=0;i<=N;i++)
    {
        ll x;scanf("%lld",&x);
        c[i]=x-ls;
        ls=x;
        ans+=cc(c[i]);
    }
    for(register ll i=1;i<=Q;i++)
    {
        ll x,y,z;
        scanf("%lld%lld%lld",&x,&y,&z);
        ans-=cc(c[x]);
        c[x]+=z;
        ans+=cc(c[x]);
        if(y!=N)
        {
            ans-=cc(c[y+1]);
            c[y+1]-=z;
            ans+=cc(c[y+1]);
        }
        printf("%lld\n",ans);
    }
    return 0;
}

一.单点修改+区间求和
https://www.luogu.com.cn/problem/P3374

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int maxn=5e5+5;
ll c[maxn],d[maxn],n,m;

void add(ll i,ll val)
{
    while(i<=n)
    {
        c[i]+=val;
        i+=i&(-i);
    }
}
ll ask(ll i)
{
    ll ret=0;
    while(i>0)
    {
        ret+=c[i];
        i-=i&(-i);
    }
    return ret;
}
int main()
{
    scanf("%lld%lld",&n,&m);
    for(ll i=1;i<=n;i++)
    {
        int h;
        scanf("%lld",&h);
        add(i,h);
    }
    for(ll i=1;i<=m;i++)
    {
        ll x,y,z;
        scanf("%lld%lld%lld",&x,&y,&z);
        if(x==1)
        {
            add(y,z);
        }
        else
        {
            cout<<ask(z)-ask(y-1)<<endl;
        }
    }
    return 0;
}

二.区间修改+单点求和(运用工具差分数组)
https://www.luogu.com.cn/problem/P3368

#include <bits/stdc++.h>

using namespace std;
const int maxn=5e5+5;
int n,m,a[maxn],c[maxn],d[maxn];
void add(int p,int x)
{
    while(p<=n)
    {
        c[p]+=x,p+=p&-p;
    }
}
void range_add(int l,int r,int x)
{
    add(l,x),add(r+1,-x);
}
int ask(int p)
{
    int res=0;
    while(p>0)
        res+=c[p],p-=p&-p;
    return res;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        add(i,a[i]-a[i-1]);
    }
    for(int i=1;i<=m;i++)
    {
        int x,y,z,p;scanf("%d",&x);
        if(x==1)
        {
            scanf("%d%d%d",&y,&z,&p);
            range_add(y,z,p);
        }
        else if(x==2)
        {
            scanf("%d",&y);
            printf("%d\n",ask(y));
        }
    }
    return 0;
}
举报

相关推荐

0 条评论