P8572 [JRKSJ R6] Eltaw 题解

注意到题目中给了一个奇怪的数据范围 \(1 \le n \cdot k \le 5 \cdot 10 ^ 5\),考虑根号分治。

  1. \(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)\)

  2. \(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;
}
posted @ 2022-10-05 12:09  tmjyh09  阅读(52)  评论(0编辑  收藏  举报