码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2020-04-09 19:13:45      阅读:108      评论:0      收藏:0      [点我收藏+]

标签:数据   树状数组   改变   一段   树状   时间复杂度   nbsp   style   下标   

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

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先写到这,树状数组明天再总结再写

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

标签:数据   树状数组   改变   一段   树状   时间复杂度   nbsp   style   下标   

原文地址:https://www.cnblogs.com/leafsblogowo/p/12668906.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!