分块总结

这几天学习了分块和莫队

“分块和莫队都是优雅的暴力”--数据结构带师wsk_1202

确实,分块的主要思想就是将两端暴力处理,中间拿tag标记或其他途径维护一下,将修改与询问的时间复杂度分摊,达到\(O(n\sqrt{n})\)的时间复杂度

这一个题库里涉及了很多分块的基本操作和用法,有时间可以多看一看

放一个分块入门1的代码

#include<bits/stdc++.h>
using namespace std;
int n,a[50003],tag[50003],pos[50003],typ,m,l,r,c;
void add(int l1,int r1,int num)
{
    for(int i=l1;i<=min(r1,pos[l1]*m);i++) //枚举左边界
        a[i]+=num;
    if(pos[l1]!=pos[r1])
        for(int i=(pos[r1]-1)*m+1;i<=r1;i++) //枚举右边界
            a[i]+=num;
    for(int i=pos[l1]+1;i<=pos[r1]-1;i++) //枚举中间的整块
        tag[i]+=num;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    m=sqrt(n); //还可以取pow(n,0.33)或pow(n,0.4)等等
    for(int i=1;i<=n;i++)
        pos[i]=(i-1)/m+1; //统计每个元素所在的块
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d%d%d",&typ,&l,&r,&c);
        if(typ==0)
            add(l,r,c);
        else
            cout<<a[r]+tag[pos[r]]<<endl;
    }
    return 0;
}

分块的代码是不是看起来就很暴力

在洛谷上写分块的时候写到了一个题,这道题巧妙地运用了分块的思想(貌似是根号分治),把原本预处理\(O(n^2)\),询问\(O(1)\),均摊一下,变成了预处理\(O(n\sqrt{n})\),询问\(O(n\sqrt{n})\),从而实现了均摊复杂度,是一种很巧妙地思想

猜你喜欢

转载自www.cnblogs.com/dzice/p/12203612.html