在一行上输入三个整数
,依次表示矩阵的行数、列数与查询次数。
此后
行,每行输入
个整数
,表示矩阵第
行的元素;共计
个整数。
此后
行,每行输入四个整数
,所有变量均满足
。
对于每一次查询,在一行上输出一个整数,表示对应子矩阵元素之和。
3 4 3 1 2 3 4 3 2 1 0 1 5 7 8 1 1 2 2 1 1 3 3 1 2 3 4
8 25 32
以第一组样例中的第二次查询
为例:
查询的子矩阵包含矩阵的左上
区域;
其内部所有元素之和为
;
因此输出
。
读入数据可能很大,请注意读写时间。
def ans(): n , m ,q = map(int, input().split(" ")) matrix = list() for _ in range(n): matrix.append(list(map(int, input().split(" ")))) dp = [[0] * (m+1) for _ in range(n+1)] for i in range(1,n+1): for j in range(1,m+1): dp[i][j] = matrix[i-1][j-1] + dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1] for _ in range(q): x1 , y1 , x2, y2 = map(int , input().split(" ")) res = dp[x2][y2] - dp[x2][y1-1] - dp[x1-1][y2] + dp[x1-1][y1-1] print(res) ans()
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); int n = in.nextInt(); int m = in.nextInt(); int q = in.nextInt(); // 原始矩阵使用1-based索引 long[][] matrix = new long[n + 1][m + 1]; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { matrix[i][j] = in.nextLong(); } } // 构建前缀和数组 long[][] prefix = new long[n + 1][m + 1]; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { prefix[i][j] = matrix[i][j] + prefix[i - 1][j] + prefix[i][j - 1] - prefix[i - 1][j - 1]; } } // 处理查询,直接打印每个结果 while (q-- > 0) { int x1 = in.nextInt(); int y1 = in.nextInt(); int x2 = in.nextInt(); int y2 = in.nextInt(); long sum = prefix[x2][y2] - prefix[x1 - 1][y2] - prefix[x2][y1 - 1] + prefix[x1 - 1][y1 - 1]; System.out.println(sum); } } }
#include <iostream> #include <vector> using namespace std; using s64_t = long long; int main() { int n = 0; int m = 0; int q = 0; while (cin >> n >> m >> q) { vector<vector<s64_t>> num(n + 1, vector<s64_t>(m + 1, 0)); for (auto i = 1; i <= n; ++i) { for (auto j = 1; j <= m; ++j) { s64_t t = 0; cin >> t; num[i][j] = t; } } vector<vector<s64_t>> sum(n + 1, vector<s64_t>(m + 1, 0)); for (auto i = 1; i <= n; ++i) { for (auto j = 1; j <= m; ++j) { sum[i][j] = num[i][j] + sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1]; } } for (auto i = 0; i < q; ++i) { int x1 = 0; int y1 = 0; int x2 = 0; int y2 = 0; cin >> x1 >> y1 >> x2 >> y2; cout << sum[x2][y2] + sum[x1 - 1][y1 - 1] - sum[x1 - 1][y2] - sum[x2][y1 - 1] << endl; } } }
const rl = require("readline").createInterface({ input: process.stdin }); var iter = rl[Symbol.asyncIterator](); const readline = async () => (await iter.next()).value; void async function () { // Write your code here let t = await get(); const n = +t[0],m = +t[1]; let k = +t[2]; const g = Array(n).fill(null); for (let i = 0 ; i < n ; i++){ g[i] = await get(); } const f = Array.from({length: n + 1}, ()=>Array(m + 1).fill(0)); for (let i = 0 ; i < n ; i++){ for (let j = 0 ; j < m ; j++){ f[i + 1][j + 1] = f[i + 1][j] + f[i][j + 1] - f[i][j] + +g[i][j]; } } while(k--){ t = await get(); const [x0,y0,x1,y1] = t; const ans = f[x1][y1] - f[x0 - 1][y1] - f[x1][y0 - 1] + f[x0 - 1][y0 - 1]; console.log(ans); } }() async function get(){ const line = await readline(); return line.split(" "); }
#include <iostream> #include <vector> using namespace std; int main() { int n, m, k; cin >> n >> m >> k; //输入数据 vector<vector<int>> arr(n + 1, vector<int>(m + 1)); //为了避免在计算时处理负索引或是 0 的复杂性,开发者选择将矩阵的大小设为 n+1 和 m+1,这样可以将每个元素的索引与其对应的逻辑位置一一对应。具体视频在前缀和第一个视频20:41 for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) cin >> arr[i][j]; //前缀和创建二维数组 vector<vector<long long>> dp(n + 1, vector<long long>(m + 1)); for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) dp[i][j] = dp[i][j - 1] + arr[i][j]; //画图理解 //dp[i][j]= dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]+arr[i][j]; //使用前缀二维数组 while (k--) { int x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2; long long sum = 0; //画图理解 //cout<<dp[x2][y2]-dp[x1-1][y2]-dp[x2][y1-1]+dp[x1-1][y1-1]<<endl; int x = 0; for (int i = x1; i <= x2; i++) { sum = dp[i][y2] - dp[i][y1 - 1] + sum; } cout << sum << endl; } } 二维前缀和就是多个一维前缀和,一样的思路
#include <stdio.h> int main() { int n,m,q,y1,x1,x2,y2; long long r=0; scanf("%d %d %d",&n,&m,&q); long long dp[n+1][m+1]; int c[n+1][m+1]; for (int i=0; i<n+1; i++) { dp[i][0]=0; } for (int i=0; i<m+1; i++) { dp[0][i]=0; } for (int i=1; i<=n; i++) { for(int j=1;j<=m;j++){ scanf("%d",&c[i][j]); dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]+c[i][j]; } } while (q--) { scanf("%d %d %d %d",&x1,&y1,&x2,&y2); r=dp[x2][y2]-dp[x2][y1-1]-dp[x1-1][y2]+dp[x1-1][y1-1]; printf("%lld\n", r); } return 0; }
#include <iostream> #include <vector> using namespace std; int main() { int n, m, q; cin >> n >> m >> q; vector<vector<int>> arr(n + 1,vector<int>(m + 1)); //二维数组 vector<vector<long long>> dp(n + 1,vector<long long>(m + 1)); //记录前缀和的矩阵数组 //dp[i][j]代表 从arr[1][1] 到arr[i][j]的所有元素之和 for(int i = 1; i < n + 1; ++i) for(int j = 1; j < m + 1; ++j) { cin >> arr[i][j]; dp[i][j] = dp[i - 1][j] + dp[i][j - 1] + arr[i][j] - dp[i - 1][j - 1]; } int x1,y1,x2,y2; while(q--) { cin >> x1 >> y1 >> x2 >> y2; cout << dp[x2][y2] - dp[x1 - 1][y2] - dp[x2][y1 - 1] + dp[x1 - 1][y1 - 1] << endl; } }
package main import ( "fmt" "os" "bufio" ) var in = bufio.NewReader(os.Stdin) func main() { var row, col, q int for { _, err := fmt.Scan(&row, &col, &q) if err != nil { break } presums := make([][]int, row+1) for i := range presums { presums[i] = make([]int, col+1) } for i := 1; i <= row; i++ { for j := 1; j <= col; j++ { fmt.Fscan(in, &presums[i][j]) } } for i := 1; i <= row; i++ { for j := 1; j <= col; j++ { presums[i][j] += presums[i-1][j] + presums[i][j-1] - presums[i-1][j-1] } } var x1, y1, x2, y2 int for q > 0 { fmt.Fscan(in, &x1,&y1,&x2,&y2) ans := presums[x2][y2] + presums[x1-1][y1-1] - presums[x1-1][y2] - presums[x2][y1-1] fmt.Println(ans) q-- } } }
import java.util.Scanner; // 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); int n = in.nextInt(); int m = in.nextInt(); int q = in.nextInt(); int[][] a = new int[n][m]; long[][] pres = new long[n + 1][m + 1]; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { a[i][j] = in.nextInt(); } } for (int i = 1; i <= n; i++) { // 当前行的前缀和 long[] lines = new long[m + 1]; lines[0] = 0; for (int j = 1; j <= m; j++) { lines[j] = lines[j - 1] + a[i - 1][j - 1]; pres[i][j] = pres[i - 1][j] + lines[j]; //System.out.print(" " + pres[i][j]); } //System.out.print("\n"); } for (int i = 0; i < q; i++) { int x1 = in.nextInt(), y1 = in.nextInt(); int x2 = in.nextInt(), y2 = in.nextInt(); //System.out.print(pres[x2][y2] +" "+ pres[x2][y1 - 1] +" "+ // pres[x1 - 1][y2] +" "+ pres[x1 - 1][y1 - 1]); System.out.println(pres[x2][y2] - pres[x2][y1 - 1] - pres[x1 - 1][y2] + pres[x1 - 1][y1 - 1]); } } }
#include <iostream> #include<vector> using namespace std; int main() { int n,m,q; cin>>n>>m>>q; vector<vector<long long>> vv; vector<long long> v1; v1.resize(m+1,0); vv.push_back(v1); for(int i=1;i<=n;i++) { vector<long long> v; v.push_back(0); for(int j=1;j<=m;j++) { long long a; scanf("%lld",&a); v.push_back(v.back()+vv[i-1][j]+a-vv[i-1][j-1]); } vv.push_back(v); } for(int i=0;i<q;i++) { int x1,x2,y1,y2; cin>>x1>>x2>>y1>>y2; printf("%lld\n",vv[y1][y2]-vv[y1][x2-1]-vv[x1-1][y2]+vv[x1-1][x2-1]); } return 0; }
import java.util.Scanner; // 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); //1.读入数据 int n = in.nextInt(), m = in.nextInt(), q = in.nextInt(); int[][] arr = new int[n + 1][m + 1]; for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) arr[i][j] = in.nextInt(); //2.处理数据 long dp[][] = new long[n + 1][m + 1]; for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) dp[i][j] = dp[i][j - 1] + dp[i - 1][j] - dp[i - 1][j - 1] + arr[i][j]; while(q > 0){ int x1 = in.nextInt(),y1 = in.nextInt(),x2 = in.nextInt(),y2 = in.nextInt(); long x = dp[x2][y2] - dp[x2][y1 - 1] - dp[x1 - 1][y2] + dp[x1 - 1][y1 - 1]; System.out.println(x); q--; } } }
#include <bits/stdc++.h> using namespace std; int main() { int n, m, q; scanf("%d %d %d", &n, &m, &q); vector<vector<int>> matrix(n + 1, vector<int>(m + 1, 0)); vector<vector<long>> dp(n + 1, vector<long>(m + 1, 0)); //实际上该题matrix可复用为dp,这里便于理解 for(int i = 1; i <= n; i++) { for ( int j = 1; j <= m; j++) { cin >> matrix[i][j]; dp[i][j] = dp[i][j - 1] + matrix[i][j]; //dp每行的值为matrix每行的前缀和 } } for(int i = 1; i <= n; i++) { for ( int j = 1; j <= m; j++) { dp[i][j] += dp[i - 1][j]; //dp[i][j]为(1,1)为左上角(i,j)为右下角的二维前缀和 } } for (int i = 0; i < q; i++) { int x1, y1, x2, y2; scanf("%d %d %d %d", &x1, &y1, &x2, &y2); printf("%ld\n", dp[x2][y2] + dp[x1 - 1][y1 - 1] - dp[x1 - 1][y2] - dp[x2][y1 - 1]); } return 0; }
package main import ( "fmt" "os" "bufio" ) var in=bufio.NewReader(os.Stdin) func main() { var n,m,q int fmt.Scan(&n,&m,&q) mat:=make([][]int,n+1) for i:=0;i<=n;i++{ mat[i]=make([]int,m+1) } var x int for i:=1;i<=n;i++{ for j:=1;j<=m;j++{ fmt.Fscan(in,&x) mat[i][j]=x+mat[i-1][j]+mat[i][j-1]-mat[i-1][j-1] } } var x1,y1,x2,y2 int for q>0{ fmt.Fscan(in,&x1,&y1,&x2,&y2) ans:=mat[x2][y2]-mat[x1-1][y2]-mat[x2][y1-1]+mat[x1-1][y1-1] fmt.Println(ans) q-- } }
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); int n = in.nextInt(), m = in.nextInt(); int q = in.nextInt(); int[][] matrix = new int[n][m]; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { matrix[i][j] = in.nextInt(); } } // 前缀和数组(分开写便于理解),int[]会溢出 long[][] preSum = new long[n + 1][m + 1]; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { // 注意与matrix数组的索引偏移 preSum[i][j] = matrix[i - 1][j - 1] + preSum[i - 1][j] + preSum[i][j - 1] - preSum[i - 1][j - 1]; } } // 计算区间和 for (int i = 0; i < q; i++) { int row1 = in.nextInt(), col1 = in.nextInt(); int row2 = in.nextInt(), col2 = in.nextInt(); // 注意与输入数据的索引偏移 System.out.println(preSum[row2][col2] - preSum[row1 - 1][col2] - preSum[row2][col1 - 1] + preSum[row1 - 1][col1 - 1]); } } }
def solution1(subnums): res1 = [0] * len(subnums) res1[0] = subnums[0] for i in range(1, len(subnums)): res1[i] = res1[i - 1] + subnums[i] return res1 def solution2(res1, nums, n, m): res2 = [[0 for i in range(m)] for j in range(n)] res2[0][0] = nums[0][0] for i in range(1, m): res2[0][i] = res2[0][i-1] + nums[0][i] for i in range(1, n): res2[i][0] = res2[i-1][0] + nums[i][0] for i in range(1, n): for j in range(1, m): res2[i][j] = res2[i - 1][j] + res2[i][j - 1] - res2[i - 1][j - 1] + nums[i][j] return res2 n, m, q = map(int, input().split()) nums = [] res1 = [] for i in range(n): nums.append(list(map(int, input().split()))) res1.append(solution1(nums[i])) res2 = solution2(res1, nums, n, m) for i in range(q): x1, y1, x2, y2 = map(int, input().split()) ans = 0 if x1 == y1 == 1: ans = res2[x2 - 1][y2 - 1] if x1 > 1 and y1 == 1: ans = ( res2[x2 - 1][y2 - 1] - res2[x1 - 2][y2 - 1] ) if x1 == 1 and y1 > 1: ans = ( res2[x2 - 1][y2 - 1] - res2[x2 - 1][y1 - 2] ) if min(x1, y1) > 1: ans = ( res2[x2 - 1][y2 - 1] - res2[x1 - 2][y2 - 1] - res2[x2 - 1][y1 - 2] + res2[x1 - 2][y1 - 2] ) print(ans)
#include<iostream> #include<vector> #include<algorithm> using namespace std; int main() { long long n,m,q; cin>>n>>m>>q; vector<long long> a; vector<vector<long long> > c; for(long long j=0;j<n;j++) { for(long long i=0;i<m;i++) { long long b; cin>>b; a.push_back(b); } c.push_back(a); a.clear(); } vector<vector<long long> > dp(n+1,vector<long long>(m+1,0)); for(long long i=0;i<n;i++) { dp[i+1][1]=dp[i][1]+c[i][0]; } for(long long j=0;j<m;j++) { dp[1][j+1]=dp[1][j]+c[0][j]; } for(long long i=2;i<=n;i++) { for(long long j=2;j<=m;j++) { dp[i][j]=dp[i][j-1]+dp[i-1][j]+c[i-1][j-1]-dp[i-1][j-1]; } } while(q) { long long count=0; long long x1,y1,x2,y2; cin>>x1>>y1>>x2>>y2; count=dp[x2][y2]-dp[x2][y1-1]-dp[x1-1][y2]+dp[x1-1][y1-1]; cout<<count<<endl; q--; } return 0; }