ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

分块

2021-07-24 23:33:22  阅读:193  来源: 互联网

标签:ch 分块 int sqrt maxm 区间


此博客仅供分块思想入门使用,如果需要进一步地了解分块,请前往笔者的 这篇博文

基本概念

分块是一种经过优化的暴力算法,它将一个长度为 \(n\) 的数组分成尽量平均的若干块,每块的长度称为块长。因为通常情况下把区间分成块长为 \(\sqrt{n}\) 的块,所以分块算法的时间复杂度通常为 \(O(m\sqrt{n})\),具体时间复杂度根据所分的块长而定。

算法思想

假如把区间分成若干个相等的块,原本在区间上进行的操作就可以变成在若干个块上进行的操作。我们通常将一个长度为 \(n\) 的数组分成 \(\sqrt{n}\) 块块长为 \(\sqrt{n}\) 的块,如果 \(n\) 不是完全平方数,则我们还会分出一个多余的块。假设待操作的区间为 \([l, r]\),我们首先判断 \(l\) 和 \(r\) 是否在同一个块内。假如它们在同一块内,我们就直接对 \(l\) 和 \(r\) 所在的块进行操作。否则,我们将区间 \([l, r]\) 分成至少两块:最左边的一块,中间的若干个被完整覆盖的块,最右边的一块。

因为最左边的一块可能没有被完全覆盖,所以我们需要枚举左边的那一块被 \([l, r]\) 覆盖的部分,直接对每一个元素进行操作,最右边的一块同理。对于中间被完整覆盖的部分,我们可以直接对整块进行操作。我们利用线段树中的 \(lazy\) 思想,直接对整块进行加上某个数之类的操作。

分块不仅可以维护区间和,还可以维护区间中有多少个小于 \(k\) 的数、区间的最大公因数等等。分块的思想其实就是 优雅的暴力,只是特判了被整体覆盖的块。

参考代码

例题链接

#include <cstdio>
#include <cmath>
using namespace std;

const int maxn = 5e5 + 5;
const int maxm = 2e3 + 5;

int n;
int a[maxn], st[maxm], ed[maxm];
int bel[maxn], lazy[maxm];

inline int read()
{
    int res = 0, flag = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            flag = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
    {
        res = res * 10 + ch - '0';
        ch = getchar();
    }
    return res * flag;
}

inline void update(int l, int r, int x)
{
    if (bel[l] == bel[r])
        for (register int i = l; i <= r; i++)
            a[i] += x;
    else
    {
        for (register int i = l; i <= ed[bel[l]]; i++)
            a[i] += x;
        for (register int i = st[bel[r]]; i <= r; i++)
            a[i] += x;
        for (register int i = bel[l] + 1; i < bel[r]; i++)
            lazy[i] += x;
    }
}

signed main()
{
    int opt, l, r, c;
    n = read();
    int block = sqrt(n);
    int size = ceil(n * 1.0 / block);
    for (register int i = 1; i <= size; i++)
    {
        st[i] = (i - 1) * block + 1;
        ed[i] = i * block;
    }
    ed[size] = n;
    for (register int i = 1; i <= n; i++)
    {
        a[i] = read();
        bel[i] = (i - 1) / block + 1;
    }
    for (register int i = 1; i <= n; i++)
    {
        opt = read();
        l = read();
        r = read();
        c = read();
        if (opt == 0)
            update(l, r, c);
        else
            printf("%d\n", a[r] + lazy[bel[r]]);
    }
    return 0;
}

标签:ch,分块,int,sqrt,maxm,区间
来源: https://www.cnblogs.com/Ling-Lover/p/fragment.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有