引子
前缀和算法适用于静态区间和查询,通过预处理每个前缀和实现快速计算任意区间和。前缀和的两大局限在于无法处理不可减运算(如区间最值、GCD)和动态修改问题。每次动态修改会导致O(n)O(n)O(n)个前缀和需要更新,整体复杂度退化为O(n2)O(n²)O(n2)。对于不可减问题和动态问题,ST表和树状数组是更优选择。
倍增算法
倍增是ST表的基础,核心思想是通过递推预计算长度为1,2,4,...(2i≤n)1,2,4,...(2^i ≤ n)1,2,4,...(2i≤n)的区间运算结果。每个位置需要预处理O(logn)O(logn)O(logn)个区间,整体构建复杂度为O(nlogn)O(nlogn)O(nlogn)。区间查询时,任意区间可拆分为最多lognlognlogn个预处理的倍增区间,利用二进制分解实现高效查询。
ST表
ST表适用于静态可重复贡献问题(如区间最值、GCD),特点是满足x与x运算结果仍为x。ST表预处理复杂度为O(nlogn)O(nlogn)O(nlogn),查询复杂度为O(1)O(1)O(1)。实现时需注意预处理对数表优化查询,将指数维度放在外层提高缓存命中率,并正确处理区间边界。
数学公式示例(区间最大值查询):
st[i][j]=max(st[i][j−1],st[i+2j−1][j−1])\text{st}[i][j] = \max(\text{st}[i][j-1], \text{st}[i + 2^{j-1}][j-1])st[i][j]=max(st[i][j−1],st[i+2j−1][j−1])
树状数组
树状数组支持单点修改和可减区间查询,基于lowbit运算实现。每个节点t[i]存储长度为lowbit(i)的区间和,前缀和可分解为至多lognlog nlogn个区间和。单点修改影响至多lognlog nlogn个区间,复杂度为O(logn)O(logn)O(logn)。实现时利用lowbit(x)=xlowbit(x)=xlowbit(x)=x&−x-x−x快速定位相关区间,空间复杂度为O(n)O(n)O(n)。
代码示例(树状数组基本操作):
int lowbit(int x){
return x&-x;
}
void add(int i,int x){
for(i;i<=n;i+=lowbit(i))s[i]+=x;
}
int sum(int i){
int ans=0;
for(i;i>=1;i-=lowbit(i)){
ans+=s[x];
}
return ans;
}
1631

被折叠的 条评论
为什么被折叠?



