- 玄关求调
T669938 Sam的羊腿小店
- @ 2025-10-23 21:04:54
求代码
1 条评论
-
-
#include <bits/stdc++.h> using namespace std; const int N = 1005; int n, m, k; int a[N][N]; long long s[N][N]; // 前缀和 long long w[N][N]; // 区间和 long long dp[2][N]; // 滚动数组 int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cin >> n >> m >> k; int M = n - k + 1; // 输入并计算前缀和、区间和 for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { cin >> a[i][j]; s[i][j] = s[i][j - 1] + a[i][j]; } for (int x = 1; x <= M; x++) { w[i][x] = s[i][x + k - 1] - s[i][x - 1]; } } // 第一天 for (int x = 1; x <= M; x++) dp[1][x] = w[1][x]; // 从第二天开始 for (int day = 2; day <= m; day++) { int cur = day & 1, pre = cur ^ 1; static long long v[N], A[N], B[N], preMax[N], sufMax[N]; for (int p = 1; p <= M; p++) { v[p] = dp[pre][p] + w[day][p]; A[p] = v[p] - s[day][p + k - 1]; B[p] = v[p] + s[day][p - 1]; } // 前缀/后缀最大值 preMax[0] = LLONG_MIN / 4; for (int i = 1; i <= M; i++) preMax[i] = max(preMax[i - 1], v[i]); sufMax[M + 1] = LLONG_MIN / 4; for (int i = M; i >= 1; i--) sufMax[i] = max(sufMax[i + 1], v[i]); deque<int> dqA, dqB; for (int x = 1; x <= M; x++) { // 维护窗口 while (!dqA.empty() && dqA.front() < x - k + 1) dqA.pop_front(); while (!dqB.empty() && dqB.front() < x) dqB.pop_front(); while (!dqA.empty() && A[dqA.back()] <= A[x]) dqA.pop_back(); dqA.push_back(x); while (!dqB.empty() && B[dqB.back()] <= B[x]) dqB.pop_back(); dqB.push_back(x); long long best = LLONG_MIN / 4; if (x - k >= 1) best = max(best, preMax[x - k]); // 左远 if (!dqA.empty()) best = max(best, s[day][x - 1] + A[dqA.front()]); // 左近 if (!dqB.empty() && dqB.front() <= x + k - 1) best = max(best, -s[day][x + k - 1] + B[dqB.front()]); // 右近 if (x + k <= M) best = max(best, sufMax[x + k]); // 右远 dp[cur][x] = w[day][x] + best; } } long long ans = 0; for (int x = 1; x <= n - k + 1; x++) ans = max(ans, dp[m & 1][x]); cout << ans << "\n"; return 0; }
- 1