P8572 [JRKSJ R6] Eltaw 题解
注意到题目中给了一个奇怪的数据范围 \(1 \le n \cdot k \le 5 \cdot 10 ^ 5\),考虑根号分治。
-
当 \(k > \sqrt{5 \cdot 10 ^ 5}\)(\(\sqrt{5 \cdot 10 ^ 5} \approx 707\))时,\(n\) 就会比较小,所以可以预处理出 \(f_{i, j}\) 来代表 \([l, r]\) 这个区间的最大值,预处理 \(\mathcal{O}(nk)\),查询 \(\mathcal{O}(1)\)。
-
当 \(k \le 707\) 时,\(n\) 较大,所以搞个前缀和来优化。查询时间复杂度 \(\mathcal{O}(k)\)。
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int M = 707;
int n, k, q;
int f[M][M];
signed main()
{
cin.tie(nullptr) -> sync_with_stdio(false);
cin >> n >> k >> q;
vector<vector<int>> a(k + 1, vector<int>(n + 1));
for (int i = 1; i <= k; i ++ )
for (int j = 1; j <= n; j ++ )
cin >> a[i][j], a[i][j] += a[i][j - 1];
if (k > M)
{
for (int i = 1; i <= n; i ++ )
{
for (int j = i; j <= n; j ++ )
{
for (int id = 1; id <= k; id ++ )
{
f[i][j] = max(f[i][j], a[id][j] - a[id][i - 1]);
}
}
}
}
while (q -- )
{
int l, r;
cin >> l >> r;
int ans = 0;
if (k <= M)
{
for (int i = 1; i <= k; i ++ )
ans = max(ans, a[i][r] - a[i][l - 1]);
cout << ans << '\n';
}
else
{
cout << f[l][r] << '\n';
}
}
return 0;
}