前缀和
1.一维模板题
AcWing 795. 前缀和(算法基础课) - AcWing
输入一个长度为 n的整数序列。
接下来再输入 m 个询问,每个询问输入一对 l,r。
对于每个询问,输出原序列中从第 l 个数到第 r个数的和。
输入格式
第一行包含两个整数 n 和 m。
第二行包含 n 个整数,表示整数数列。
接下来 m 行,每行包含两个整数 l 和 r,表示一个询问的区间范围。
输出格式
共 m 行,每行输出一个询问的结果。
数据范围
1≤l≤r≤n1,  
1≤n,m≤1000001,  
−1000≤数列中元素的值≤1000
输入样例:
1 2 3 4 5
| 5 3 2 1 3 6 4 1 2 1 3 2 4
|
输出样例:
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader;
public class Main02 { public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); String[] s = in.readLine().split(" "); int n = Integer.parseInt(s[0]); int m = Integer.parseInt(s[1]); int[] num = new int[n + 1]; s = in.readLine().split(" "); for (int i = 0; i < n; i++) { num[i + 1] = num[i] + Integer.parseInt(s[i]); } while (m-- > 0) { s = in.readLine().split(" "); int a = Integer.parseInt(s[0]); int b = Integer.parseInt(s[1]); System.out.println(num[b] - num[a - 1]); } } }
|
2.二维模板题
796. 子矩阵的和 - AcWing题库
输入一个 n 行 m 列的整数矩阵,再输入 q 个询问,每个询问包含四个整数 x1,y1,x2,y2表示一个子矩阵的左上角坐标和右下角坐标。
对于每个询问输出子矩阵中所有数的和。
输入格式
第一行包含三个整数 n,m,q。
接下来 n行,每行包含 m 个整数,表示整数矩阵。
接下来 q行,每行包含四个整数 x1,y1,x2,y2,表示一组询问。
输出格式
共 q 行,每行输出一个询问的结果。
数据范围
1≤n,m≤10001
1≤q≤200000
1≤x1≤x2≤n
1≤y1≤y2≤m
−1000≤矩阵内元素的值≤1000
输入样例:
1 2 3 4 5 6 7
| 3 4 3 1 7 2 4 3 6 2 8 2 1 2 3 1 1 2 2 2 1 3 4 1 3 3 4
|
输出样例:
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader;
public class Main { public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); String[] s = in.readLine().split(" "); int n = Integer.parseInt(s[0]); int m = Integer.parseInt(s[1]); int q = Integer.parseInt(s[2]); int[][] num = new int[n + 1][m + 1]; for (int i = 1; i <= n; i++) { s = in.readLine().split(" "); for (int j = 1; j <= m; j++) { num[i][j] = num[i - 1][j] + num[i][j - 1] - num[i - 1][j - 1] + Integer.parseInt(s[j - 1]); } } while (q-- > 0) { s = in.readLine().split(" "); int x1 = Integer.parseInt(s[0]); int y1 = Integer.parseInt(s[1]); int x2 = Integer.parseInt(s[2]); int y2 = Integer.parseInt(s[3]); System.out.println(num[x2][y2] - num[x2][y1 - 1] - num[x1 - 1][y2] + num[x1 - 1][y1 - 1]); } } }
|
3.一维训练题
3956. 截断数组 - AcWing题库
给定一个长度为 n 的数组 a1,a2,…,an
现在,要将该数组从中间截断,得到三个非空子数组。
要求,三个子数组内各元素之和都相等。
请问,共有多少种不同的截断方法?
输入格式
第一行包含整数 n。
第二行包含 n 个整数 a1,a2,…,an
输出格式
输出一个整数,表示截断方法数量。
数据范围
前六个测试点满足 1≤n≤10
所有测试点满足 1≤n≤105,−10000≤ai≤10000
输入样例:
输出样例:
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader;
public class Main { public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); int n = Integer.parseInt(in.readLine()); String[] s = in.readLine().split(" "); if(n < 3) { System.out.println(0); return; } int[] nums = new int[n + 1]; for(int i = 0 ; i < n; i++) { nums[i + 1] = nums[i] + Integer.parseInt(s[i]); } if(nums[n] % 3 != 0) { System.out.println(0); return; } long res = 0; long cnt = 0; for(int i = 2; i < n; i++) { if(nums[i - 1] == nums[n] / 3) { cnt++; } if(nums[i] == nums[n] / 3 * 2) { res += cnt; } } System.out.println(res); } }
|
4.一维蓝桥杯真题省赛B组
1230. K倍区间 - AcWing题库
给定一个长度为 N 的数列,A1,A2,…AN,如果其中一段连续的子序列 Ai,Ai+1,…Aj之和是 K 的倍数,我们就称这个区间 [i,j] 是 K 倍区间。
你能求出数列中总共有多少个 K倍区间吗?
输入格式
第一行包含两个整数 N 和 K。
以下 N 行每行包含一个整数 Ai。
输出格式
输出一个整数,代表 K 倍区间的数目。
数据范围
1≤N,K≤100000
1≤Ai≤100000
输入样例:
输出样例:
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader;
public class Main { public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); String[] s = in.readLine().split(" "); int n = Integer.parseInt(s[0]); int k = Integer.parseInt(s[1]); long[] num = new long[n + 1]; long[] pre = new long[k + 1]; long res = 0; for (int i = 1; i <= n; i++) { num[i] = num[i - 1] + Integer.parseInt(in.readLine()); int t = (int)(num[i] % k); res += pre[t]; pre[t]++; if(t == 0) { res++; } } System.out.println(res); } }
|
5.二维算法竞赛进阶指南
99. 激光炸弹 - AcWing题库
地图上有 N 个目标,用整数 Xi,Yi表示目标在地图上的位置,每个目标都有一个价值 Wi。
注意:不同目标可能在同一位置。
现在有一种新型的激光炸弹,可以摧毁一个包含 R×R个位置的正方形内的所有目标。
激光炸弹的投放是通过卫星定位的,但其有一个缺点,就是其爆炸范围,即那个正方形的边必须和 x,y轴平行。
求一颗炸弹最多能炸掉地图上总价值为多少的目标。
输入格式
第一行输入正整数 N 和 R,分别代表地图上的目标数目和正方形包含的横纵位置数量,数据用空格隔开。
接下来 N 行,每行输入一组数据,每组数据包括三个整数 Xi,Yi,Wi,分别代表目标的 x 坐标,y 坐标和价值,数据用空格隔开。
输出格式
输出一个正整数,代表一颗炸弹最多能炸掉地图上目标的总价值数目。
数据范围
0≤R≤109
0<N≤10000
0≤Xi,Yi≤5000
0≤Wi≤1000
输入样例:
输出样例:
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader;
public class Main { public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); String[] s = in.readLine().split(" "); int n = Integer.parseInt(s[0]); int r = Integer.parseInt(s[1]); long[][] num = new long[5001][5001]; long[][] sum = new long[5002][5002]; for (int i = 0; i < n; i++) { s = in.readLine().split(" "); int x = Integer.parseInt(s[0]); int y = Integer.parseInt(s[1]); int w = Integer.parseInt(s[2]); num[x][y] += w; } for (int i = 0; i < 5001; i++) { for (int j = 0; j < 5001; j++) { sum[i + 1][j + 1] = sum[i + 1][j] + sum[i][j + 1] - sum[i][j] + num[i][j]; } } long res = 0; if (r >= 5000) { System.out.println(sum[5001][5001]); } else { r = r - 1; for (int i = 1; i < 5002 - r; i++) { for (int j = 1; j < 5002 - r; j++) { res = Math.max(res, sum[i + r][j + r] - sum[i - 1][j + r] - sum[i + r][j - 1] + sum[i - 1][j - 1]); } } System.out.println(res); } } }
|