[数据结构学习]分块与树状数组

Posted leafsblogowo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[数据结构学习]分块与树状数组相关的知识,希望对你有一定的参考价值。

分块与树状数组均在区间问题上有重要的应用

emm分块效率上不如树状数组,但是思路比较好想

先说分块:

将n个数的序列分为sqrt(n)块,预处理每块数据的信息以加快后续对区间信息的查询

先上一段代码:

const int maxn = 5e5 + 50;
int sum[maxn],a[maxn],l[maxn],r[maxn],belong[maxn];
int block,num;

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 <= num; i++){
        for(int j = l[i]; j <= r[i]; j++)
            belong[j] = i, sum[i] += a[j];
    }
}

代码中的全局变量有这些是需要预处理的:sum[i]表示第i块数据的和(也可是异或和、乘积这类,一样的)

a[i]为第i个数据,l[i],r[i]分别为第i块的左右端点下标,belong[i]存储第i个数所属的分块

预处理过后,贴上单点修改/更新和区间查询的代码:

inline void update(int x, int y){
    a[x] += y;
    sum[belong[x]] += y;
}

inline int query(int x, int y){
    int ans = 0;
    if(belong[x] == belong[y]){
        for(int i = x; i <= y; i++)
            ans += a[i];
        return ans;
    }
    for(int i = x; i <= r[belong[x]]; i++)
        ans += a[i];
    for(int i = belong[x] + 1; i < belong[y]; i++)
        ans += sum[i];
    for(int i = l[belong[y]]; i <= y; i++)
        ans += a[i];
    return ans;
}

其中对单点进行数据更新只需将数组a中数据改变,再将下标为x所属的块的总和增加y即可

而查询区间[x,y]的和,分块这里采用的是暴力求和

1.当x,y在同一块中时,遍历求和

2.当x,y不在同一块,遍历求和x到x所属块的右边界,再加上sum[x+1]到sum[y-1],再遍历求和y所属块的左边界到y

时间复杂度均为O(sqrt(n)) 单点修改为O(1)

 

qwq先写到这,树状数组明天再总结再写

以上是关于[数据结构学习]分块与树状数组的主要内容,如果未能解决你的问题,请参考以下文章

[分块] 分块入门1~4

bzoj3295动态逆序对 分块+树状数组

Bzoj 2141: 排队 分块,逆序对,树状数组

CodeChef FNCS (分块+树状数组)

综合数论/因子分解/分块/莫比乌斯反演/树状数组HDU4947

综合数论/因子分解/分块/莫比乌斯反演/树状数组HDU4947