分块讲解

临近NOIP,我要复习各种学过的算法,先从暴力开始吧!

分块就是把一个待求的序列分成√n块.之后暴力查找。分整块和散块两部分。所有信息在当前结点和块内同时维护。每次查询O(3*√n)。修改不一定。一般是O(1)--O(√n) 之间。

这就是分块,原理及其简单。但写起来需要考虑一些细节。

比如:洛谷P1816 忠诚 求区间最小值问题。

我们还是可以把查询分成整块和散块两种,预处理每块内最小值与每个数在哪个块。这样方便O(1)查询。

帖代码:

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
#define N 100010
int n,Q;
int belong[N];
int minn[400];
int a[N];
int block,ans;
int query(int x,int y)
{
    int minx=0x3f3f3f3f;
    for(int i=x;i<=min(belong[x]*block,y);i++)
        minx=min(minx,a[i]);
    if(belong[x]!=belong[y])
        for(int i=(belong[y]-1)*block+1;i<=y;i++)
            minx=min(minx,a[i]);
    for(int i=belong[x]+1;i<belong[y];i++)
        minx=min(minx,minn[i]);
    return minx;
}
int main()
{
    memset(minn,0x3f,sizeof(minn));
    scanf("%d%d",&n,&Q);
    block=sqrt(n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        belong[i]=(i-1)/block+1;
        minn[belong[i]]=min(a[i],minn[belong[i]]);
    }
    for(int i=1;i<=Q;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        ans=query(x,y);
        printf("%d ",ans);
    }
}

细节需要自己思考!

原文地址:https://www.cnblogs.com/342zhuyongqi/p/9800986.html