# Prefix Sum# Array# Query

a694 - 吞食天地二

🔗 前往 ZeroJudge 原題

題目描述

題目要求計算一個 n x n 的矩陣中,給定區塊 (x1, y1) 到 (x2, y2) 的所有元素的總和。輸入包含多組測試案例,每組案例包含矩陣的大小 n 和查詢次數 m,以及矩陣元素和查詢座標。

解題思路

本題的核心思想是使用前綴和 (Prefix Sum) 技術來高效地計算矩陣區塊的和。首先,我們建立一個前綴和矩陣 sum,其中 sum[i][j] 儲存了原始矩陣中 (1, 1) 到 (i, j) 的所有元素的總和。

計算前綴和矩陣的公式如下:

sum[i][j] = sum[i][j-1] + sum[i-1][j] - sum[i-1][j-1] + matrix[i][j]

有了前綴和矩陣,我們就可以在 O(1) 的時間內計算任何子矩陣的和。給定一個區塊 (x1, y1) 到 (x2, y2),其總和可以通過以下公式計算:

total = sum[x2][y2] - sum[x2][y1-1] - sum[x1-1][y2] + sum[x1-1][y1-1]

複雜度分析

  • 時間複雜度: O(n^2 + m)
    • 建立前綴和矩陣需要 O(n^2) 的時間。
    • 處理 m 個查詢,每個查詢需要 O(1) 的時間,總共需要 O(m) 的時間。
  • 空間複雜度: O(n^2)
    • 需要額外 O(n^2) 的空間來儲存前綴和矩陣。

程式碼

#include <stdio.h>
int main() {
	int n,m,x1,y1,x2,y2,i,j,temp,total;
	while(scanf("%d%d",&n,&m)!=EOF){
		int sum[n+1][n+1];
		for(i=0;i<=n;i++){
			sum[0][i]=0;
			sum[i][0]=0;
		}
		for(i=1;i<=n;i++)
			scanf("%d",&temp),sum[1][i]=sum[1][i-1]+temp;
		for(i=2;i<=n;i++){
			for(j=1;j<=n;j++){
				scanf("%d",&temp);
				sum[i][j]=sum[i][j-1]+sum[i-1][j]-sum[i-1][j-1]+temp;
			}
		}
		for(i=0;i<m;i++){
			scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
			total=sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-1];
			printf("%d\n",total);
		}
	}

}

Discussion