- 1.前缀和
前缀和也就是将【l,r】区间内的数据进行累加
注意事项:
模板
S[i] = a[1] + a[2] + … a[i]
a[l] + … + a[r] = S[r] - S[l - 1]
1.数组从1开始可以保证公式的适用性。
则,
【1,10】=S10-S0(如果S0有数据就不对应了)
【l r】=Sr - Sl-1;
题目:
输入一个长度为 n 的整数序列。
接下来再输入 m 个询问,每个询问输入一对 l,r。
对于每个询问,输出原序列中从第 l 个数到第 r 个数的和。
输入格式
第一行包含两个整数 n 和 m。
第二行包含 n 个整数,表示整数数列。
c++:
java、
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
/*
* 输入一个长度为 n 的整数序列。
接下来再输入 m 个询问,每个询问输入一对 l,r。
对于每个询问,输出原序列中从第 l 个数到第 r 个数的和。
*
5 3
2 1 3 6 4
1 2
1 3
2 4*/
public class Main {
//1,注意计数从1开始计数,方便使用公式
//2,开辟新数组放置新的数据
static int Number = 100010;
public static int frontadd(int[] S,int l,int r){
//利用公式
int add = S[r] - S[l-1];
return add;
}
public static void main(String[] args) throws IOException {
Scanner sc =new Scanner(System.in);
//先输入
int N = sc.nextInt();
int q = sc.nextInt();
int[] A = new int[N+1];
int[] S = new int[N+1];
S[0] =0;
//数组
for(int i =1;i<=N;i++){
A[i] = sc.nextInt();
}
//计算出数组的和Sn
for(int k=1;k<=N;k++){
S[k] = S[k-1]+A[k];
}
for(int j=0;j<q;j++){
//每次接收两个数据
int qus1 = sc.nextInt();
int qus2 = sc.nextInt();
int add = frontadd(S,qus1,qus2);
System.out.println(add);
}
}
}
- 二维前缀和
二维数组,容斥原理
模板
S[i, j] = 第i行j列格子左上部分所有元素的和
以(x1, y1)为左上角,(x2, y2)为右下角的子矩阵的和为:
S[x2, y2] - S[x1 - 1, y2] - S[x2, y1 - 1] + S[x1 - 1, y1 - 1]
单个的怎么进行计算:
Sij = Si-1,j +Si,j-1-Si-1j-1+aij
减去重复的数据
题目:
输入一个 n 行 m 列的整数矩阵,再输入 q 个询问,每个询问包含四个整数 x1,y1,x2,y2,表示一个子矩阵的左上角坐标和右下角坐标。
对于每个询问输出子矩阵中所有数的和。
import java.util.Scanner;
/*第一行包含三个整数 n,m,q。接下来 n 行,每行包含 m 个整数,表示整数矩阵。接下来 q 行,每行包含四个整数 x1,y1,x2,y2,表示一组询问。
输出格式共 q 行,每行输出一个询问的结果。
数据范围
1≤n,m≤1000,
1≤q≤200000,
1≤x1≤x2≤n,
1≤y1≤y2≤m,
−1000≤矩阵内元素的值≤1000*/
public class Main {
static int M=1000;
static int Q = 200000;
//main
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int q = sc.nextInt();//几组查询
//定义二维数组
int[][] A = new int[n+1][m+1];
//定义S和的数组
int[][] S = new int[n+1][m+1];
//输入数组
A[0][0]=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
A[i][j] = sc.nextInt();
}
}
//计算和
S[0][0] =0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
S[i][j] = S[i][j-1]+S[i-1][j]-S[i-1][j-1]+A[i][j];//所有的和的放在数组里面
}
}
//输入两个坐标()()左上角和右上角
for(int i=0;i<q;i++){
//i
int Xi = sc.nextInt();
int Yi = sc.nextInt();
int Xj = sc.nextInt();
int Yj = sc.nextInt();
//求之间的围城的面积
int s = mianji(S,Xi,Yi,Xj,Yj);
System.out.println(s);
}
}
public static int mianji(int[][] S,int Xi,int Yi,int Xj,int Yj){
int s = S[Xj][Yj] - S[Xi-1][Yj]-S[Xj][Yi-1]+S[Xi-1][Yi-1];
return s;
}
}
注意面积公式!!