熱門文章

2025年7月14日 星期一

ZeroJudge 解題筆記:a694. 吞食天地二

作者:王一哲
日期:2025年7月14日


ZeroJudge 題目連結:a694. 吞食天地二

解題想法


題目中的 x 軸應該是對應到列,y 軸對應到欄,有點奇怪。解題技巧主要利用的是二維前綴和,産生前綴和的原則
psum[i][j] = psum[i-1][j] + psum[i][j-1] - psum[i-1][j-1]
因為 $psum[i-1][j-1]$ 會被多加一次,最後要扣掉。用前綴和取範圍 $[r1, c1]$ 到 $[r2, c2]$ 區間和的原則
isum = psum[r2][c2] - psum[r1-1][c2] - psum[r2][c1-1] + psum[r1-1][c1-1]
因為 $psum[r1-1][c1-1]$ 會被多扣一次,最後要加回來。

Python 程式碼


使用時間約為 0.7 s,記憶體約為 8 MB,通過測試。
import sys

for line in sys.stdin:
    n, m = map(int, line.split())
    psum = [[0]*(n+1) for _ in range(n+1)]  # 最上面、最左邊補 0
    for i in range(1, n+1):  # 讀取 n 行資料
        row = [0] + list(map(int, sys.stdin.readline().split()))
        for j in range(1, n+1):  # 處理前綴和
            psum[i][j] = psum[i-1][j] + psum[i][j-1] - psum[i-1][j-1] + row[j]
    for _ in range(m):  # 讀取 m 行
        r1, c1, r2, c2 = map(int, sys.stdin.readline().split())
        isum = psum[r2][c2] - psum[r1-1][c2] - psum[r2][c1-1] + psum[r1-1][c1-1]
        sys.stdout.write(f"{isum:d}\n")


C++ 程式碼


使用時間約為 71 ms,記憶體約為 432 kB,通過測試。
#include <cstdio>
#include <cstring>
using namespace std;

int main() {
    int n, m;
    while(scanf("%d %d", &n, &m) != EOF) {
        int psum[n+1][n+1];
        memset(psum, 0, sizeof(psum));
        for(int i=1; i<=n; i++) {
            for(int j=1; j<=n; j++) {
                int p; scanf("%d", &p);
                psum[i][j] = psum[i-1][j] + psum[i][j-1] - psum[i-1][j-1] + p;
            }
        }
        for(int i=0; i<m; i++) {
            int r1, c1, r2, c2;
            scanf("%d %d %d %d", &r1, &c1, &r2, &c2);
            printf("%d\n", psum[r2][c2] - psum[r1-1][c2] - psum[r2][c1-1] + psum[r1-1][c1-1]);
        }
    }
    return 0;
}


沒有留言:

張貼留言