ACwing-795.前缀和
输入一个长度为n的整数序列。
接下来再输入m个询问,每个询问输入一对l, r。
对于每个询问,输出原序列中从第l个数到第r个数的和。
输入格式
第一行包含两个整数n和m。
第二行包含n个整数,表示整数数列。
接下来m行,每行包含两个整数l和r,表示一个询问的区间范围。
输出格式
共m行,每行输出一个询问的结果。
数据范围
1≤l≤r≤n,
1≤n,m≤100000,
−1000≤数列中元素的值≤1000
输入样例:
5 3
2 1 3 6 4
1 2
1 3
2 4
输出样例:
3
6
10
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.TreeMap;
public class Main {
static Scanner sc = new Scanner(System.in);
static int n,m;
static int[] sum = new int[100005];
public static void main(String[] args) {
n = sc.nextInt();
m = sc.nextInt();
for(int i = 1; i <= n; i++) {
sum[i] = sc.nextInt();
sum[i] += sum[i-1];
}
while(m-- > 0) {
int l = sc.nextInt(), r = sc.nextInt();
System.out.println(sum[r] - sum[l-1]);
}
}
}
ACwing-796. 子矩阵的和
输入一个n行m列的整数矩阵,再输入q个询问,每个询问包含四个整数x1, y1, x2, y2,表示一个子矩阵的左上角坐标和右下角坐标。
对于每个询问输出子矩阵中所有数的和。
输入格式
第一行包含三个整数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
输入样例:
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
输出样例:
17
27
21
再ACwing中不能过,后台数据有问题,是用的字符串,故要分割;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.TreeMap;
public class Main {
static Scanner sc = new Scanner(System.in);
static int n,m,q;
static int[][] sum = new int[1005][1005];
public static void main(String[] args) {
n = sc.nextInt();m = sc.nextInt();q = sc.nextInt();
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
sum[i][j] = sc.nextInt();
sum[i][j] += sum[i][j-1] + sum[i-1][j] - sum[i-1][j-1];
}
}
while(q-- > 0) {
int x1,y1,x2,y2;
x1 = sc.nextInt();y1 = sc.nextInt();x2 = sc.nextInt();y2 = sc.nextInt();
System.out.println(sum[x2][y2] - sum[x1-1][y2] - sum[x2][y1-1] + sum[x1-1][y1-1]);
}
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.TreeMap;
public class Main {
static Scanner sc = new Scanner(System.in);
static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
static int n,m,q;
static int[][] sum = new int[1005][1005];
public static void main(String[] args) throws IOException {
String[] str = reader.readLine().split(" ");
n = Integer.parseInt(str[0]);
m = Integer.parseInt(str[1]);
q = Integer.parseInt(str[2]);
for(int i = 1; i <= n; i++) {
String[] str1 = reader.readLine().split(" ");
for(int j = 1; j <= m; j++) {
sum[i][j] = Integer.valueOf(str1[j-1]);
sum[i][j] += sum[i][j-1] + sum[i-1][j] - sum[i-1][j-1];
}
}
while(q-- > 0) {
String[] str1 = reader.readLine().split(" ");
int x1,y1,x2,y2;
x1 = Integer.parseInt(str1[0]);
y1 = Integer.parseInt(str1[1]);
x2 = Integer.parseInt(str1[2]);
y2 = Integer.parseInt(str1[3]);
System.out.println(sum[x2][y2] - sum[x1-1][y2] - sum[x2][y1-1] + sum[x1-1][y1-1]);
}
}
}
ACwing-99. 激光炸弹
利用矩阵和,将前面的价值全部加起来,放入前缀和里。
然后一个个边长为r的矩阵递推出最大的矩阵价值
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.TreeMap;
public class Main {
static Scanner sc = new Scanner(System.in);
static int n,r;
static int[][] sum = new int[5005][5005];
public static void main(String[] args) {
n = sc.nextInt();
r = sc.nextInt();
int max = r , may = r, ans = -9;
for(int i = 1; i <= n; i++) {
int x = sc.nextInt()+1, y = sc.nextInt()+1,w = sc.nextInt();
sum[x][y] = w;
if(x > max)max = x;
if(y > may)may = y;
if(w > ans)ans = w;
}
for(int i = 1; i <= max; i++) {
for(int j = 1; j <= may; j++) {
sum[i][j] = sum[i][j] + sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1];
}
}
for(int i = r; i <= max; i++) {
for(int j = r; j <= may; j++) {
ans = Math.max(ans, sum[i][j] - sum[i - r][j] - sum[i][j - r] + sum[i - r][j - r]);
}
}
System.out.println(ans);
}
}
AcWing 1230. K倍区间
给定一个长度为 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
输入样例:
5 2
1
2
3
4
5
输出样例:
6
普通做法O(n^2)
利用前缀和,枚举每一个子序列,判断是否是k的倍数。
if((sum[j] - sum[i]) % k == 0)ans++;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.TreeMap;
public class Main {
static Scanner sc = new Scanner(System.in);
static int n,k;
static int[] sum = new int[100005];
public static void main(String[] args) {
n = sc.nextInt();
k = sc.nextInt();
int ans = 0;
for(int i = 1; i <= n; i++) {
sum[i] = sc.nextInt();
sum[i] += sum[i-1];
}
for(int i = 0; i < n; i++) {
for(int j = i+1; j <= n; j++) {
if((sum[j] - sum[i]) % k == 0)ans++;
}
}
System.out.println(ans);
}
}
优化代码O(N)
观察以下代码
if((sum[j] - sum[i]) % k == 0)ans++;
可得, sum[j] % k - sum[i] % k == 0;
所以 sum[j] % k == sum[i] % k;
故可以利用一个数组a 存储前缀和的余K的值,当余数相同时,其子序列区间和是k的倍数。
又因为 一个数余K 等于0,则其本身也是k的倍数,所有初值a[0] = 1;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.TreeMap;
public class Main {
static Scanner sc = new Scanner(System.in);
//static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
static int n,k;
static int[] sum = new int[100005];
static int[] a = new int[100005];
public static void main(String[] args) {
n = sc.nextInt();
k = sc.nextInt();
for(int i = 1; i <= n; i++) {
sum[i] = sc.nextInt();
sum[i] += sum[i-1];
sum[i] = sum[i]%k;
}
long ans = 0;
a[0] = 1;
for(int i = 1; i <= n; i++) {
ans += a[sum[i]];//如果有3个数的余数相同,根据 由前向后枚举 可得 答案为1 + 2 = 3;
a[sum[i]]++;
}
System.out.println(ans);
}
}