一维前缀和
简单来说:我们有一个数组x和它的前缀和数组y,他们满足以下公式。 y 0 = x 0 y 1 = x 0 + x 1 y 2 = x 0 +
x 1 + x 2 … 即 y[n]=x[1]+x[2]+…+x[n]。
import java.util.Scanner;
public class 一维前缀和 {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int m=sc.nextInt();
int[] arr=new int[n+1];
//为了方便,数组下标从1开始
for (int i = 1; i <=n ; i++) {
arr[i]=sc.nextInt();
}
//下标从1开始,就可以避免l=1的特判
int[] sum=new int[n+1];
for (int i = 1; i <=n ; i++) {
sum[i]=sum[i-1]+arr[i];//前缀和的初始化
}
while (m-->0){ //m次询问(询问数组的区间和)
int l=sc.nextInt();
int r=sc.nextInt();
System.out.println(sum[r]-sum[l-1]);
}
}
}
二维前缀和
应用:快速求子矩阵的和
import java.util.Scanner;
public class 二维前缀和 {
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[][] map=new int[n+1][m+1];
for (int i = 1; i <=n ; i++) {
for (int j = 1; j <=m ; j++) {
map[i][j]=sc.nextInt();
}
}
int[][] sum=new int[n+1][m+1];
//初始化二维数组,防止下标越界
sum[0][0]=0;
sum[0][1]=0;
sum[1][0]=0;
//求二维前缀和
for (int i = 1; i <=n ; i++) {
for (int j = 1; j <=m ; j++) {
sum[i][j]=sum[i][j-1]+sum[i-1][j]-sum[i-1][j-1]+map[i][j];
}
}
while (q-->0){
int x1=sc.nextInt();
int y1=sc.nextInt();
int x2=sc.nextInt();
int y2=sc.nextInt();
//求子矩阵的面积
System.out.println(sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1]);
}
}
}
3.一维差分
import java.util.Scanner;
public class 一维差分 {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int m=sc.nextInt();
int[] arr=new int[n+2];
int[] cha=new int[n+2];
for (int i = 1; i <=n ; i++) {
arr[i]=sc.nextInt();
}
for (int i = 1; i <=n ; i++) {
cha[i]=arr[i]-arr[i-1];
}
while (m-->0){
int l=sc.nextInt();
int r=sc.nextInt();
int c=sc.nextInt();
cha[l]+=c;
cha[r+1]-=c;
}
for (int i = 1; i <=n ; i++) {
arr[i]=arr[i-1]+cha[i];
}
for (int i = 1; i <=n ; i++) {
System.out.print(arr[i]+" ");
}
}
}
4.二维差分
数据大时要用BuffereRead输入
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class 二维差分 {
static int N=1005;
static int[][] a=new int[N][N];
static int[][] b=new int[N][N];
public static void main(String[] args) throws IOException {
int n=Reader.nextInt();
int m=Reader.nextInt();
int q=Reader.nextInt();
for (int i = 1; i <=n ; i++) {
for (int j = 1; j <=m ; j++) {
a[i][j]=Reader.nextInt();
}
}
//进行差分操作
for (int i = 1; i <=n ; i++) {
for (int j = 1; j <=m ; j++) {
insert(i,j,i,j,a[i][j]);
}
}
while (q-->0){
int x1=Reader.nextInt();
int y1=Reader.nextInt();
int x2=Reader.nextInt();
int y2=Reader.nextInt();
int c=Reader.nextInt();
insert(x1,y1,x2,y2,c);
}
//还原原数组
for (int i = 1; i <=n ; i++) {
for (int j = 1; j <=m ; j++) {
b[i][j]+=b[i-1][j]+b[i][j-1]-b[i-1][j-1];
}
}
for (int i = 1; i <=n ; i++) {
for (int j = 1; j <=m ; j++) {
System.out.print(b[i][j]+" ");
}
System.out.println();
}
}
//差分操作
static void insert(int x1,int y1,int x2,int y2,int c){
b[x1][y1]+=c;
b[x2+1][y1]-=c;
b[x1][y2+1]-=c;
b[x2+1][y2+1]+=c;
}
}
class Reader{
static BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
static StringTokenizer tokenizer=new StringTokenizer("");
static String next() throws IOException {
while (!tokenizer.hasMoreTokens()){
tokenizer=new StringTokenizer(reader.readLine());
}
return tokenizer.nextToken();
}
static int nextInt() throws IOException {
return Integer.parseInt(next());
}
}