标签:pac 模板 根据 amp bit 查询 its 状态转移方程 nlogn
区间最大值,nlogn预处理,1查询,不能动态修改。
令 $f[i][j]$ 表示 $[i,i+2^j-1]$ 的最大值。
显然, $f[i][0]=a[i]$ 。
根据定义式,写出状态转移方程: $f[i][j]=max(f[i][j-1],f[i+2^{j-1}][j-1])$ 。
我们可以这么理解:将区间 $[i,i+2^j-1]$ 分成相同的两部分
中点即为 $(i+(i+2^j-1))/2=i+2^{j-1}-1/2$
所以 $[i,i+2^j-1]$ 可以分成 $[i,i+2^{j-1}-1]$ 和 $[i+2^j,i+2^j-1]$
对于每个询问 $[x,y]$ ,我们把它分成两部分 $f[x][s],f[y-2^s+1][s]$
其中 $s=log_2(y-x+1)$ ,虽然这两个区间有重叠,但是重叠不会影响区间的最大值
#include <bits/stdc++.h> using namespace std; const int logn = 21; const int maxn = 2000001; long long a[maxn], f[maxn][logn], Logn[maxn]; inline int read() { char c = getchar(); int x = 0, f = 1; while (c < ‘0‘ || c > ‘9‘) { if (c == ‘-‘) f = -1; c = getchar(); } while (c >= ‘0‘ && c <= ‘9‘) { x = x * 10 + c - ‘0‘; c = getchar(); } return x * f; } void pre() { Logn[1] = 0; Logn[2] = 1; for (int i = 3; i <= maxn; i++) { Logn[i] = Logn[i / 2] + 1; } } int main() { int n = read(), m = read(); for (int i = 1; i <= m; i++) f[i][0] = read(); pre(); for (int j = 1; j <= logn; j++) for (int i = 1; i + (1 << j) - 1 <= n; i++) f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]); for (int i = 1; i <= m; i++) { int x = read(), y = read(); int s = Logn[y - x + 1]; printf("%d\n", max(f[x][s], f[y - (1 << s) + 1][s])); } return 0; }
标签:pac 模板 根据 amp bit 查询 its 状态转移方程 nlogn
原文地址:https://www.cnblogs.com/Yinku/p/10472788.html