【题目链接】
【思路要点】
- 对于每个询问,本质不同的\(\sqrt{|i-j|}\)只有\(O(\sqrt{N})\)级别。
- 因此,我们在询问时根据这一点将序列分成\(O(\sqrt{N})\)个区间,分别查询每个区间的最大值即可。
- 由于每个区间的长度也是\(O(\sqrt{N})\)级别的,我们并不需要记录一个ST表,只需要暴力预处理每个点向后\(1\)至\(K\)个数的最大值即可,其中\(K\)在\(O(\sqrt{N})\)级别。
- 时空复杂度\(O(N\sqrt{N})\)。
【代码】
#include<bits/stdc++.h> using namespace std; const int MAXN = 100005; const int MAXK = 1005; template <typename T> void chkmax(T &x, T y) {x = max(x, y); } template <typename T> void chkmin(T &x, T y) {x = min(x, y); } template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> void writeln(T x) { write(x); puts(""); } int n, val[MAXN], suf[MAXN][MAXK]; int main() { read(n); for (int i = 1; i <= n; i++) read(val[i]); for (int i = 1; i <= n; i++) { suf[i][1] = val[i]; for (int j = 2; j < MAXK && i + j - 1 <= n; j++) suf[i][j] = max(suf[i][j - 1], val[i + j - 1]); } for (int i = 1; i <= n; i++) { int ans = 0, pos, j, nxt; pos = i, j = 1, nxt = i; while (pos != 1) { nxt = pos - 1; pos -= j * 2 - 1; if (pos <= 0) pos = 1; chkmax(ans, suf[pos][nxt - pos + 1] - val[i] + j); j++; } pos = i, j = 1, nxt = i; while (nxt != n) { pos = nxt + 1; nxt += j * 2 - 1; if (nxt >= n) nxt = n; chkmax(ans, suf[pos][nxt - pos + 1] - val[i] + j); j++; } writeln(ans); } return 0; }