ST表
无修改区间最值询问问题
• 给出一个数组a[1..N]
• Q个询问,每次询问每次询问区间[x,y]最大值。
• N,Q <= 100000
St表的递推
• 用st[k][i]表示从i开始连续2^k个元素的最值。
• 得出递推式
• st[k+1][i]=max(st[k][i], st[k][i+2^k]);(假设求最大值)
• 从小到大枚举k,再枚举i。
• 那么预处理出上面这个数组的复杂度为O(nlogn) 。
询问操作
• 找出最大的k使得 2^k<=y-x+1
• 注意到[x,x+2^k-1], [y-2^k+1,y]两个子区间覆盖原区间[x,y]
• 那么答案就是max(st[k][x], st[k][y-(2^k)+1]).
• k= log2 (y-x+1) 向下取整
• 小技巧:内建函数计算log
• #define log(x) (31-__builtin_clz(x))
• 有用的性质
• 求多个数最大值时,同一个值重复出现多次和出现次效果是相同的
• St表主要运用于在没有修改的情况需要能快速求解区间最值的情况。
Sparse table 时间复杂度
• 预处理: O(nlogn)
• 每次询问: O(1)
LCA
• 给定一棵树。
• Q个询问,每次询问某两个点(x,y)的最近公共祖先
• 考虑两个相同深度的节点的lca
• 如果同时往上走k步到达相同节点,则往上走k+1步仍然相同
• for(int k=20;k>=0;k--)
• if (st[x][k] != st[y][k]) x = st[x][k], y=st[y][k];
• lca=fa[x]=fa[y];
• 对于深度不同的节点,可先将深度大的往上走到深度相同
• 小技巧:内建函数计算log
• #define log(x) (31-__builtin_clz(x))
• If (dep[x]<dep[y]) swap(x,y);
• while (dep[x] > dep[y]) x = st[x][log(dep[x]-dep[y])];
原文地址:https://www.cnblogs.com/Mary-Sue/p/9345817.html