https://leetcode.cn/problems/sliding-window-maximum/description/
这个题用优先队列就慢了,每次调整要logn,总的nlogn
要想O(n)需要预处理
有两种预处理方法
查询红色区间,要将它分成两个等长的绿色区间(允许重叠但不能超过了)
绿条的长度是 2 m 2^m 2m,其中 2 m < = 查询区间长度 2^m<=查询区间长度 2m<=查询区间长度
需要把所有的 2 i 2^i 2i区间的值都算出来先
例:{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
在这个阶段,每层都能用到上一层的,比方说[1, 8]=[1, 4]+[5, 8]
[i, i+ 2 p o w e r 2^{power} 2power] = [i, i+ 2 p o w e r − 1 2^{power-1} 2power−1] + [ i+ 2 p o w e r − 1 2^{power-1} 2power−1, (i+ 2 p o w e r − 1 2^{power-1} 2power−1)+ 2 p o w e r − 1 2^{power-1} 2power−1]
int log(x){
if(!x) return 0;
return 1+log(x/2);
}
更快的递推打表:
Logn[1] = 0;
Logn[2] = 1;
for (int i = 3; i < maxn; i++) {
Logn[i] = Logn[i / 2] + 1;
}
1< A[log(n)][n] ST表用在这题是没问题的,但是如果换个题,里面元素会改,就很麻烦,这种情况用线段树比较好 查询[2, 7] 用若干个大小为 2 x 2^x 2x的块拼成查询区间 更新之类的,下次做到对应的题再研究吧,什么懒标记的ST存储
建表模板
for (int power = 1; power <= logn; power++)
for (int i = 1; i + (1 << power) - 1 <= n; i++){
f[power][i] = max(f[power - 1][i], f[power - 1][i + (1 << (power - 1))]);
线段树
初始化
怎么用
[1, 10]
[1, 5] + [6, 10]
[1, 3] + [4, 5] + [6, 8] [9, 10]
[1, 2], [3], [4, 5], [6, 7], [8]
[1], [2], [3], [4, 5], [6, 7]// [ql, qr] 为查询区间
int ql, qr;
// [s, t] 为当前节点包含的区间, p 为当前节点的编号
int getsum(int s, int t, int p) {
if (l <= s && t <= r) return d[p];
int m = s + ((t - s) >> 1), sum = 0;
if (ql <= m) sum += getsum(s, m, p * 2);
if (qr > m) sum += getsum(m + 1, t, p * 2 + 1);
return sum;
}
ans=getsum(1, N, 1);