求代码

1 条评论

  • @ 2025-10-23 21:06:39
    #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