分块算法的学习

分块

将区间长度为n的数组分成sqrt (n)个块,每块的大小是sqrt (n)。
对区间[L,R]进行操作:
如果在一个块里面,暴力更新即可。O(sqrt n)级别。
不在一个块里面:
开头一部分,暴力更新,O(sqrt n)级别。
结尾一部分,暴力更新,O(sqrt n)级别。
中间连续的块,打一个延迟标记,不用更新到具体的点,O(sqrt n)级别。

b站链接:https://www.bilibili.com/video/av6445624?from=search&seid=17541052966933649532

建立分块

const int maxn=1e6+7;
int n,m;
int num,block;//块数,块的大小
int belong[maxn];//第i个数属于哪一块
int l[maxn],r[maxn];//l[i]表示第i块的最左边的元素,r[i]表示第i块的最右边的元素
int a[maxn];//原数组
int p[maxn];//延迟标记
int d[maxn];//将a数组进行块内排序后的数组

void build()
{
    block=sqrt(n);
    num=n/block;if(n%block) num++;
    for(int i=1;i<=num;i++)
        l[i]=(i-1)*block+1,r[i]=i*block;
    r[num]=n;
    for(int i=1;i<=n;i++)
    {
        belong[i]=(i-1)/block+1;
        d[i]=a[i];
    }
    for(int i=1;i<=num;i++)
        sort(d+l[i],d+r[i]+1);//块内排序
}

单点更新


void update(int x,int y) //单点更新,将第x个的值加y
{
    a[x]+=y;
    Max[belong[x]]=max(Max[belong[x]],a[x]);
}


区间查询最大值

long long ask(int x,int y) //区间查询,[x,y]的最大值
{
    long long ans=0;
    if(belong[x]==belong[y])
    {
        for(int i=x;i<=y;i++)
            ans=max(a[i],ans);
        return ans;
    }
    for(int i=x;i<=r[belong[x]];i++)//最前一部分
        ans=max(ans,a[i]);
    for(int i=belong[x]+1;i<belong[y];i++)//中间完整的块
        ans=max(ans,Max[i]);
    for(int i=l[belong[y]];i<=y;i++)//最后一部分
        ans=max(ans,a[i]);
    return ans;
}

猜你喜欢

转载自blog.csdn.net/qq_37685156/article/details/81361040
今日推荐