前缀和与差分代码模板

常用算法代码模板总结

前缀和与差分互为逆运算

目录

一维前缀和

练习题目:前缀和

二维前缀和

练习题目:子矩阵的和

一维差分

练习题目:差分

二维差分

练习题目:差分矩阵


一维前缀和

一个长度为n的一维数组

a1 , a2 , a3 …… an

其前缀和数组如下

a1 , (a1+a2) , (a1+a2+a3) …… (a1+a2+a3+……+an)

练习题目:前缀和

 java题解

import java.util.Scanner;

public class Main {

	public static void main(String args[]) {
		Scanner input = new Scanner(System.in);
		int n = input.nextInt();
		int k = input.nextInt();
		int[] nums = new int[n + 10];
		int[] result = new int[n + 10];

		for (int i = 1; i <= n; i++) {//从第一个下标位置开始接收数据
			nums[i] = input.nextInt();
		}

		for (int i = 1; i <= n; i++) {//求前缀和,上面从第一个下标位置开始接收数据方便求前缀和
			result[i] = result[i - 1] + nums[i];//一步一步的刷新数组,这一步的前缀和等于上一步的前缀和加上这一步的数字
		}
		
		for (int i = 0; i < k; i++) {//输出查询结果
			int left = input.nextInt();
			int right = input.nextInt();
			System.out.println(result[right] - result[left - 1]);
		}

	}
}

二维前缀和

i行j列的二维数组,其前缀和表示意义如下

而要求某一部分的面积,可如下表示 

10048_a9580464dc-前缀和.png (738×724)

练习题目:子矩阵的和

java题解

import java.util.Scanner;

public class Main {

	public static void main(String args[]) {
		Scanner input = new Scanner(System.in);
		int n = input.nextInt();//n行
		int m = input.nextInt();//m列
		int q = input.nextInt();//q次询问
		int[][] nums = new int[n + 10][m + 10];
		int[][] result = new int[n + 10][m + 10];//记录二维前缀和的数组

		for (int i = 1; i <= n; i++) {//接收数据
			for (int j = 1; j <= m; j++) {
				nums[i][j] = input.nextInt();
			}
		}
		
		for (int i = 1; i <= n; i++) {//求前缀和
			for (int j = 1; j <= m; j++) {
				result[i][j] = nums[i][j] + result[i - 1][j] + result[i][j - 1] - result[i - 1][j - 1];// 求二维前缀和
			}
		}
		
		for (int i = 0; i < q; i++) {//计算矩阵面积 
			int x1 = input.nextInt();
			int y1 = input.nextInt();
			int x2 = input.nextInt();
			int y2 = input.nextInt();
			System.out.println(result[x2][y2] - result[x1 - 1][y2] - result[x2][y1 - 1] + result[x1 - 1][y1 - 1]);// 输出某一部分的二维前缀和
		}

	}

}

一维差分

一个长度为n的一维数组

a1 , (a1+a2) , (a1+a2+a3) …… (a1+a2+a3+……+an)

其差分数组如下

a1 , a2 , a3 …… an

​​​​​​​练习题目:差分

java题解

import java.util.Scanner;

public class Main {
	static int[] result = new int[100010];

	public static void Insert(int left, int right, int number) {
		result[left] += number;
		result[right + 1] -= number;
	}

	public static void main(String args[]) {

		Scanner input = new Scanner(System.in);
		int n = input.nextInt();//n个整数
		int m = input.nextInt();//m次操作
		int[] nums = new int[n + 10];

		for (int i = 1; i <= n; i++) {//接收数据
			nums[i] = input.nextInt();
		}

		for (int i = 1; i <= n; i++)// 求差分数组
			Insert(i, i, nums[i]);

		for (int i = 0; i < m; i++) {//l到r之间的每个数加上c,相当于差分数组在l处加c,在r+1处减c取前缀和
			int l = input.nextInt();//这里r+1处必须要减c,不然就是l之后全部加c
			int r = input.nextInt();
			int c = input.nextInt();
			Insert(l, r, c);
		}
		int[] prefix = new int[100010];
		for (int i = 1; i <= n; i++) {//求前缀和
			prefix[i] = prefix[i - 1] + result[i];
		}
		for (int i = 1; i <= n; i++) {//输出
			System.out.print(prefix[i] + " ");
		}

	}
}

二维差分

和求二维前缀和数组有相同之处

练习题目:差分矩阵

java题解

import java.util.Scanner;

public class Main {

	static int[][] result = new int[1010][1010];
    // 构造差分数组和更新差分数组是同一个道理
	public static void Insert(int x1, int y1, int x2, int y2, int number) {
		result[x1][y1] += number;
		result[x1][y2 + 1] -= number;
		result[x2 + 1][y1] -= number;
		result[x2 + 1][y2 + 1] += number;
	}

	public static void main(String args[]) {
		Scanner input = new Scanner(System.in);
		int n = input.nextInt();//n行
		int m = input.nextInt();//m列
		int q = input.nextInt();//q次操作
		int[][] nums = new int[n + 10][m + 10];

		for (int i = 1; i <= n; i++) {//接收数据
			for (int j = 1; j <= m; j++)
				nums[i][j] = input.nextInt();
		}

		for (int i = 1; i <= n; i++) {//求二维差分数组
			for (int j = 1; j <= m; j++) {
				Insert(i, j, i, j, nums[i][j]);
			}
		}

		for (int i = 0; i < q; i++) {//处理操作
			int x1 = input.nextInt();
			int y1 = input.nextInt();
			int x2 = input.nextInt();
			int y2 = input.nextInt();
			int num = input.nextInt();
			Insert(x1, y1, x2, y2, num);
		}

		for (int i = 1; i <= n; i++) {//再求二维前缀和数组
			for (int j = 1; j <= m; j++)
				result[i][j] = result[i][j] + result[i - 1][j] + result[i][j - 1] - result[i - 1][j - 1];
		}
		for (int i = 1; i <= n; i++) {//输出
			for (int j = 1; j <= m; j++)
				System.out.print(result[i][j] + " ");
			System.out.println();
		}

	}
}

  • 12
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

算不出来没办法

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值