简单前缀和

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);
	}
}
发布了115 篇原创文章 · 获赞 6 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/foolishpichao/article/details/104111239