之前用线段树做的,后来试了一下发现这道题可以用分块通过,请问分块的时间复杂度是 O(mn) 吗,属于正解吗?
代码如下:
#include<bits/stdc++.h>
template<typename T> T max(T a, T b){return (a>b)?a:b;}
template<typename T> T min(T a, T b){return (a<b)?a:b;}
template<typename T> T gcd(T a, T b){while(b^=a^=b^=a%=b); return a;}
const char endl='\n';
const int inf=0x3f3f3f3f;
const int MAXN=100000+5;
const int SQ=500+5;
long long st[SQ], ed[SQ], size[SQ], bel[MAXN];
long long arr[MAXN], sum[SQ], mark[SQ];
void init(long long n)
{
    long long block=sqrt(n);
    for(long long i=1;i<=block;i++)
    {
        st[i]=n/block*(i-1)+1;
        ed[i]=n/block*i;
    }
    ed[block]=n;
    for(long long i=1;i<=block;i++)
        for(long long j=st[i];j<=ed[i];j++)
            bel[j]=i;
    for(long long i=1;i<=block;i++)
        size[i]=ed[i]-st[i]+1;
}
void update_section(long long l, long long r, long long v)
{
    if(bel[l]==bel[r])
    {
        for(long long i=l;i<=r;i++)
        {
            arr[i]+=v;
            sum[bel[i]]+=v;
        }
    }
    else
    {
        for(long long i=l;i<=ed[bel[l]];i++)
        {
            arr[i]+=v;
            sum[bel[i]]+=v;
        }
        for(long long i=st[bel[r]];i<=r;i++)
        {
            arr[i]+=v;
            sum[bel[i]]+=v;
        }
        for(long long i=bel[l]+1;i<bel[r];i++)
            mark[i]+=v;
    }
}
long long search_section(long long l, long long r)
{
    long long s=0;
    if(bel[l]==bel[r])
    {
        for(long long i=l;i<=r;i++)
            s+=arr[i]+mark[bel[i]];
    }
    else
    {
        for(long long i=l;i<=ed[bel[l]];i++)
            s+=arr[i]+mark[bel[i]];
        for(long long i=st[bel[r]];i<=r;i++)
            s+=arr[i]+mark[bel[i]];
        for(long long i=bel[l]+1;i<bel[r];i++)
            s+=sum[i]+mark[i]*size[i];
    }
    return s;
}
int main()
{
    long long n, m;
    scanf("%lld%lld", &n, &m);
    for(long long i=1;i<=n;i++)
        scanf("%lld", &arr[i]);
    init(n);
    long long block=sqrt(n);
    for(long long i=1;i<=block;i++)
        for(long long j=st[i];j<=ed[i];j++)
            sum[i]+=arr[j];
    while(m--)
    {
        long long op;
        scanf("%lld", &op);
        if(op==1)
        {
            long long l, r, v;
            scanf("%lld%lld%lld", &l, &r, &v);
            update_section(l, r, v);
        }
        else if(op==2)
        {
            long long l, r;
            scanf("%lld%lld", &l, &r);
            printf("%lld\n", search_section(l, r));
        }
    }
    return 0;
}