HDU 1166

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166

题解:

本题作为一个模板题,我用它来检验过总查询时间复杂度为 $O(q log n)$ 的树状数组模板、线段树模板以及zkw线段树模板;而今天,我们要来用分块来写这道题目。

时间复杂度:

初始化 $O(n)$;每次修改均为 $O(1)$,每次查询为 $O(sqrt n)$;总时间复杂度 $O(n + q sqrt n)$。

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e4+10;

int n;

int a[maxn],sum[maxn];
int block[maxn],len,tot;
int L[maxn],R[maxn];
void init(int l,int r)
{
    memset(sum,0,sizeof(sum));
    len=sqrt(r-l+1);
    tot=0;
    for(int i=l;i<=r;i++)
    {
        block[i]=(i-l)/len+1;
        tot=max(block[i],tot);
        sum[block[i]]+=a[i];
        if(i==l) L[block[i]]=i;
        if(i==r) R[block[i]]=r;
        if(l<=i-1 && i<=r && block[i-1]!=block[i])
        {
            R[block[i-1]]=i-1;
            L[block[i]]=i;
        }
    }
}
void add(int p,int x)
{
    a[p]+=x;
    sum[block[p]]+=x;
}
int ask(int l,int r)
{
    int st=block[l],ed=block[r];
    int res=0;
    if(st==ed) for(int i=l;i<=r;i++) res+=a[i];
    else
    {
        for(int i=l;i<=R[st];i++) res+=a[i];
        for(int i=st+1;i<=ed-1;i++) res+=sum[i];
        for(int i=L[ed];i<=r;i++) res+=a[i];
    }
    return res;
}

int main()
{
    int T;
    cin>>T;
    for(int kase=1;kase<=T;kase++)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        init(1,n);
        printf("Case %d:
",kase);
        char op[6];
        while(scanf("%s",op))
        {
            if(op[0]=='E') break;
            if(op[0]=='Q')
            {
                int l,r;
                scanf("%d%d",&l,&r);
                printf("%d
",ask(l,r));
            }
            else if(op[0]=='A')
            {
                int pos,x;
                scanf("%d%d",&pos,&x);
                add(pos,x);
            }
            else if(op[0]=='S')
            {
                int pos,x;
                scanf("%d%d",&pos,&x);
                add(pos,-x);
            }
        }
    }
}
原文地址:https://www.cnblogs.com/dilthey/p/9746445.html