70分求调

P3372 【模板】线段树 1

gq520520 @ 2024-08-10 10:24:48

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m,xl,xr;
int a[100010],t[400010],v[400010],sum,k;
inline int ls(int x)
{
    return x<<1;
}
inline int rs(int x)
{
    return x<<1|1;
}
int build(int x,int l,int r)
{
    int m;
    if(l==r) return t[x]=a[l];
    m=((l+r)>>1);
    return t[x]=build(ls(x),l,m)+build(rs(x),m+1,r);
}
void add(int p,int l,int r)
{
    int m;
    if(r<xl||l>xr) return ;
    if(l>=xl&&r<=xr)
    {
        v[p]+=k;
        return ;
    }
    if(l<=xr&&l>xl&&r>xr) t[p]+=k*(xr-l+1);
    else if(r>=xl&&r<xr&&l<xl) t[p]+=k*(r-xl+1);
    else if(l<=xl&&r>=xr) t[p]+=k*(xr-xl+1);
    m=((l+r)>>1);
    add(ls(p),l,m);
    add(rs(p),m+1,r);
}
void findd(int p,int l,int r)
{
    if(r<xl||l>xr) return ;
    if(v[p])
    {
        t[p]+=v[p]*(r-l+1);
        v[ls(p)]+=v[p];
        v[rs(p)]+=v[p];
        v[p]=0;
    }
    if(l>=xl&&r<=xr)
    {
        sum+=t[p];
        return ;
    }
    int m=(l+r)>>1;
    findd(ls(p),l,m);
    findd(rs(p),m+1,r);
}
signed main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    cin>>a[i];
    build(1,1,n);
    int p;
    for(int i=1;i<=m;i++)
    {
        cin>>p;
        if(p==1)
        {
            cin>>xl>>xr>>k;
            add(1,1,n);
        }
        else
        {
            cin>>xl>>xr;
            sum=0;
            findd(1,1,n);
            cout<<sum<<endl;
        }
    }
    return 0;
}

by ABCgfed @ 2024-08-10 10:42:51

线段树要开八倍(因为你叶子节点下传了)


|