日期: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;
}
沒有留言:
張貼留言