求助分块时间复杂度
查看原帖
求助分块时间复杂度
420139
vectorli1楼主2021/7/8 14:02

之前用线段树做的,后来试了一下发现这道题可以用分块通过,请问分块的时间复杂度是 O(mn)O(m\sqrt{n}) 吗,属于正解吗?
代码如下:

#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;
}
2021/7/8 14:02
加载中...