蓝桥杯备赛系列——倒计时50天!

news2024/11/17 14:26:32

蓝桥杯备赛系列

倒计时50天!

前缀和和差分

知识点

**前缀和数组:**假设原数组用a[i]表示,前缀和数组用sum[i]表示,那么sum[i]表示的是原数组前i项之和,注意一般用前缀和数组时,原数组a[i]的有效下标是从1开始的。式子如下,
s u m [ n ] = ∑ i = 1 n a [ i ] sum[n]=\sum_{i=1}^n a[i] sum[n]=i=1na[i]
**差分数组:**假设原数组用a[i]表示,差分数组用d[i]表示,那么d[i]表示的是a[i]和a[i-1]之差,注意一般用差分数组时,原数组a[i]的有效下标也是从1开始的。式子如下,
d [ n ] = a [ i ] − a [ i − 1 ] d[n]=a[i]-a[i-1] d[n]=a[i]a[i1]
接下来看一下前缀和和差分的模板题。

前缀和模板

题目描述

给定一个长度为 n n n的数组 a 1 , a 2 , . . . . a n . a_1,a_2,....a_n. a1,a2,....an.

接下来有 q q q次查询, 每次查询有两个参数 l , r l, r l,r.

对于每个询问, 请输出 a l + a l + 1 + . . . + a r . a_l+a_{l+1}+...+a_r. al+al+1+...+ar.

输入描述

第一行包含两个整数 n n n q q q.

第二行包含n个整数, 表示 a 1 , a 2 , . . . . a n . a_1,a_2,....a_n. a1,a2,....an.

接下来q行,每行包含两个整数 l和r.

1 ≤ n , q ≤ 1 0 5 1≤n,q≤10^5 1n,q105
− 1 0 9 ≤ a [ i ] ≤ 1 0 9 −10^9≤a[i]≤10^9 109a[i]109
1 ≤ l ≤ r ≤ n 1≤l≤r≤n 1lrn

输出描述

输出 q q q行,每行代表一次查询的结果.

样例输入

3 2
1 2 4
1 2
2 3

样例输出

3
6
题目分析

前缀和最经典的一个作用就是以O(1)的时间复杂度求区间和。

sum[l-1]=a[1]+a[2]+a[3]+…+a[l-1]

sum[r]=a[1]+a[2]+a[3]+…+a[l-1]+a[l]+…+a[r]

sum[r]-sum[l-1]=a[1]+a[2]+a[3]+…+a[l-1]+a[l]+…+a[r]-(a[1]+a[2]+a[3]+…+a[l-1])

​ =a[l]+a[l+1]+…+a[r]

所以区间[l,r]的和可以用sum[r]-sum[l-1]表示。

题目代码
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
	Scanner scanner = new Scanner(System.in);
	int n = scanner.nextInt();
	int q = scanner.nextInt();
	int a[] = new int[n+1];
	long sum[] = new long[n+1];
	for(int i = 1;i <= n;i++) a[i] = scanner.nextInt();
	for(int i = 1;i <= n;i++) sum[i] = sum[i-1] + a[i];
	while(q-- > 0) {
		int l = scanner.nextInt();
		int r = scanner.nextInt();
		System.out.println(sum[r]-sum[l-1]);
	}
}
}
二维前缀和模板

题目描述

给你一个 n 行 m 列的矩阵 A ,下标从1开始。

接下来有 q 次查询,每次查询输入 4 个参数 x 1 , y 1 , x 2 , y 2 x1 , y1 , x2 , y2 x1,y1,x2,y2

请输出以 ( x 1 , y 1 ) (x1, y1) (x1,y1)为左上角 ,$ (x2,y2)$ 为右下角的子矩阵的和,

输入描述

第一行包含三个整数n,m,q.

接下来n行,每行m个整数,代表矩阵的元素

接下来q行,每行4个整数 x 1 , y 1 , x 2 , y 2 x1, y1, x2, y2 x1,y1,x2,y2,分别代表这次查询的参数

1 ≤ n , m ≤ 1000 1≤n,m≤1000 1n,m1000
1 ≤ q ≤ 1 0 5 1≤q≤10^5 1q105
− 1 0 9 ≤ a [ i ] [ j ] ≤ 1 0 9 −10^9≤a[i][j]≤10^9 109a[i][j]109
1 ≤ x 1 ≤ x 2 ≤ n 1≤x1≤x2≤n 1x1x2n
1 ≤ y 1 ≤ y 2 ≤ m 1≤y1≤y2≤m 1y1y2m

输出描述

输出q行,每行表示查询结果。

样例输入

3 4 3
1 2 3 4
3 2 1 0
1 5 7 8
1 1 2 2
1 1 3 3
1 2 3 4

样例输出

8
25
32
题目分析

我们通过图片分析如何求二维前缀和数组以及如何利用二维前缀和数组求矩阵和。

如何求二维前缀和数组。如图所示,假设要求 s u m [ x 1 ] [ y 1 ] sum[x1][y1] sum[x1][y1]的值,也就是图中大红色圈起来的部分,我们可以将蓝色部分加上绿色部分后再加上x1,y1处本来的值,也就是 s u m [ x 1 ] [ y 1 − 1 ] + s u m [ x 1 − 1 ] [ y 1 ] + a [ x 1 ] [ y 1 ] sum[x1][y1-1]+sum[x1-1][y1]+a[x1][y1] sum[x1][y11]+sum[x11][y1]+a[x1][y1]。但是这样会多加上一部分,也就是蓝色和绿色重叠的部分,他用 s u m [ x 1 − 1 ] [ y 1 − 1 ] sum[x1-1][y1-1] sum[x11][y11]表示,需要减掉。综上 s u m [ x 1 ] [ y 1 ] = s u m [ x 1 ] [ y 1 − 1 ] + s u m [ x 1 − 1 ] [ y 1 ] + a [ x 1 ] [ y 1 ] − s u m [ x 1 − 1 ] [ y 1 − 1 ] sum[x1][y1]=sum[x1][y1-1]+sum[x1-1][y1]+a[x1][y1]-sum[x1-1][y1-1] sum[x1][y1]=sum[x1][y11]+sum[x11][y1]+a[x1][y1]sum[x11][y11]

如何利用二维前缀和数组求矩阵和。如图所示,假设要求左上角下标为x1,y1,右下角下标为x2,y2的矩阵的值,也就是图中蓝色的部分。可以用 s u m [ x 2 ] [ y 2 ] − s u m [ x 2 ] [ y 1 − 1 ] − s u m [ x 1 − 1 ] [ y 2 ] + s u m [ x 1 − 1 ] [ y 1 − 1 ] sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-1] sum[x2][y2]sum[x2][y11]sum[x11][y2]+sum[x11][y11]表示,也就是图中绿色部分减去图中橙色和紫色部分,而紫色和橙色部分有重叠,多减了,要再加回来,也就是图中棕色部分。

题目代码

代码细节,数据的读入涉及到矩阵,对于java而言数据量较大,要使用快读。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
public static void main(String[] args) throws IOException {
	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	String[] strings = br.readLine().split(" ");
	int n = Integer.parseInt(strings[0]);
	int m = Integer.parseInt(strings[1]);
	int q = Integer.parseInt(strings[2]);
	long a[][] = new long[n+1][m+1];
	long sum[][] = new long[n+1][m+1];
	for(int i = 1;i <= n;i++) {
		strings = br.readLine().split(" ");
		for(int j = 1;j <= m;j++) {
			a[i][j] = Integer.parseInt(strings[j-1]);
		}
	}
	
	for(int i = 1;i <= n;i++) {
		for(int j = 1;j <= m;j++) {
			sum[i][j] = sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];
		}
	}
	while(q-- > 0) {
		strings = br.readLine().split(" ");
		int x1 = Integer.parseInt(strings[0]);
		int y1 = Integer.parseInt(strings[1]);
		int x2 = Integer.parseInt(strings[2]);
		int y2 = Integer.parseInt(strings[3]);
		System.out.println(sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-1]);
	}
}
}

差分模板题

题目描述

给你一个长度为n的正数数组 a 1 , a 2 , . . . . a n a_1,a_2,....a_n a1,a2,....an

接下来对这个数组进行m次操作,每个操作包含三个参数l,r,k,代表将数组中 a l + a l + 1 + . . . + a r a_l+a_{l+1}+...+a_r al+al+1+...+ar部分都加上k。

请输出操作后的数组。

输入描述

第一行包含两个整数n和m。
第二行包含n个整数表示 a 1 , a 2 , . . . . a n a_1,a_2,....a_n a1,a2,....an
接下来是m行,每行三个整数,分别代表每次操作的参数l,r,k.

1 ≤ n , m ≤ 1 0 5 1≤n,m≤10^5 1n,m105
− 1 0 9 ≤ a [ i ] ≤ 1 0 9 −10^9≤a[i]≤10^9 109a[i]109
1 ≤ l ≤ r ≤ n 1≤l≤r≤n 1lrn
− 1 0 9 ≤ k ≤ 1 0 9 −10^9≤k≤10^9 109k109

输出描述

输出1行,表示m次操作后的 a 1 , a 2 , . . . . a n a_1,a_2,....a_n a1,a2,....an

输入样例

3 2
1 2 3
1 2 4
3 3 -2

输出样例

5 6 1
题目分析

差分数组一般要结合前缀和使用,使用方法如下,

假设我有两个操作,第一个操作是对下标为3一直到下标为10的数字都加上2,第二个操作是对下标为4到下标为7的数字都加上3,朴素的做法是遍历一遍要操作的数组区间,然后执行操作就可以了,两次操作过后,原始数组累计要改变的值如下,

a的下标1234567891011
a要加上的值00255552220

这样做执行每次操作的时间复杂度是数组的长度。那么如何利用差分数组来做呢?

对下标为3一直到下标为10的数字都加上2——>d[3]+=2,d[11]-=2。

对下标为4到下标为7的数字都加上3——>d[4]+=3,d[8]-=3。

然后求d数组的前缀和数组,结果如下,下标从1开始

sum的下标1234567891011
sum的值00255552220

此时sum里面的值表示的是原始数组要变动的值,将sum数组与原始数组相加,即是操作后的结果,可以发现是和表1一样的。而这样每次操作的时间复杂度是O(1)。

综上,如果我要对区间[l,r]里的数加上k,我只需要对差分数组进行操作,即d[l]+=k,d[r+1]-=k。

题目代码
import java.util.Scanner;

public class Main {
public static void main(String[] args) {
	Scanner scanner = new Scanner(System.in);
	int n = scanner.nextInt();
	int m = scanner.nextInt();
	long[] a = new long[n+1];
	long[] s = new long[n+1];
	for (int i = 1; i < a.length; i++) {
		a[i] = scanner.nextInt();
	}
	while(m>0) {
		m--;
		int l = scanner.nextInt();
		int r = scanner.nextInt();
		int k = scanner.nextInt();
	    s[l] += k;
	    if(r+1<=n) {
	    	s[r+1]-=k;
	    }
	}
	long sum[] = new long[n+1];
	for (int i = 1; i < s.length; i++) {
		sum[i] = sum[i-1]+s[i];
		a[i] = a[i]+sum[i];
		System.out.print(a[i] +" ");
	}
}
}
二维差分模板题

题目描述

给你一个n行m列的矩阵,下标从1开始。
接下来有q次操作,每次操作输入5个参数x1, y1, x2, y2, k
表示把以(x1, y1)为左上角,(x2,y2)为右下角的子矩阵的每个元素都加上k,
请输出操作后的矩阵。

输入描述

第一行包含三个整数n,m,q.
接下来n行,每行m个整数,代表矩阵的元素

接下来q行,每行5个整数x1, y1, x2, y2, k,分别代表这次操作的参数

1 ≤ n , m ≤ 1000 1≤n,m≤1000 1n,m1000
1 ≤ q ≤ 1 0 5 1≤q≤10^5 1q105
1 ≤ x 1 ≤ x 2 ≤ n 1≤x1≤x2≤n 1x1x2n
1 ≤ y 1 ≤ y 2 ≤ m 1≤y1≤y2≤m 1y1y2m
− 1 0 9 ≤ 矩阵中的元素 ≤ 1 0 9 −10^9≤矩阵中的元素≤10^9 109矩阵中的元素109

输出描述

输出n行,每行m个数,每个数用空格分开,表示这个矩阵。

样例输入

2 3 4
1 2 3
4 5 6
1 1 2 2 3
1 2 2 3 -1
1 1 1 3 4
1 1 2 1 1

样例输出

9 8 6
8 7 5
题目分析

二维差分模板关键在于确定好在差分数组的哪些地方更改值。假设要更改的地方是从下标(2,4)到下标(3,6)的位置加1,那么首先必然是让(2,4)的位置加1,这样之后对差分数组求前缀和的结果如图所示,

我们要更改的是绿色圈起来的部分,但是之外的部分也更改了,我需要把这部分更改变回来,我想让(2,6)之后的从(2,7)开始都是0,既然(2,4)加了1,那么对应的(2,7)这一部分之后我要减掉1,来抵消前面的加1。同样,(4,4)也要减1来抵消(2,4)的加1。这样就可以了吗?这样相当于有两个位置减1,一个位置加1,一看也不对呀,对于(4,7)这个位置应该是没有变化的,但是它的前缀和所包含的格子里(2,4)加了1,(2,7)减了1,(4,4)也减了1,相当于(4,7)这个位置减了1,我们要把这个减1抵消,所以要在(4,7)这里加1。

综上,对(x1,y2)到(x2,y2)的格子都进行加k操作,只需要(x1,y1)+=k,(x1,y2+1)-=k,(x2+1,y1)-=k,(x2+1,y2+1)+=k。

然后对差分数组求二维前缀和之后,把结果累加到原始数组上就可以了。

题目代码
import java.util.Scanner;
public class Main{
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int n = scanner.nextInt();
		int m = scanner.nextInt();
		int q = scanner.nextInt();
		long[][] a = new long[n + 1][m + 1];
		long[][] b = new long[n + 1][m + 1];
		long[][] sum = new long[n + 1][m + 1];
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= m; j++) {
				a[i][j] = scanner.nextLong();
			}
		}
		while ((q--) != 0) {
			int x1 = scanner.nextInt();
			int y1 = scanner.nextInt();
			int x2 = scanner.nextInt();
			int y2 = scanner.nextInt();
			int k = scanner.nextInt();
			b[x1][y1] += k;
			if (y2 + 1 <= m) {
				b[x1][y2 + 1] -= k;
			}
			if (x2 + 1 <= n) {
				b[x2 + 1][y1] -= k;
			}
			if (x2 + 1 <= n && y2 + 1 <= m) {
				b[x2 + 1][y2 + 1] += k;
			}
		}

		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= m; j++) {
				sum[i][j] = sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+b[i][j];
				a[i][j] += sum[i][j];
				System.out.print(a[i][j] + " ");
			}
			System.out.println();
		}

	}
}
abb

题目描述

leafee 最近爱上了 abb 型语句,比如“叠词词”、“恶心心”

leafee 拿到了一个只含有小写字母的字符串,她想知道有多少个 “abb” 型的子序列?
定义: abb 型字符串满足以下条件:

  1. 字符串长度为 3 。
  2. 字符串后两位相同。
  3. 字符串前两位不同。

输入描述

第一行一个正整数 n

第二行一个长度为 n 的字符串(只包含小写字母)

1 ≤ n ≤ 1 0 5 1≤n≤10^5 1n105

输出描述

“abb” 型的子序列个数。

样例输入

6
abcbcc

样例输出

8

共有1个abb,3个acc,4个bcc

题目分析

在abcbcc中,acc的个数为3,他是哪3个呢?可以看下图,a的后面有3个c,在这3个c里面任选两个c可以和a组成一个叠词,那么组合的种类为 C 3 2 C_3^2 C32也就是 3 ∗ 2 / 2 = 3 3*2/2=3 32/2=3种。假设字母a后面有num个相同的字母,那么它能够贡献的叠词个数为 C n u m 2 C_{num}^2 Cnum2,也就是 n u m ∗ ( n u m − 1 ) / 2 num*(num-1)/2 num(num1)/2个。因此我们需要求出每个字母后面出现的其它相同字母的个数。

在这里插入图片描述

对于上图字符串,因为求的是后面的字符出现的次数,所以我们倒序遍历去求。位置6c出现了一次,用 n u m [ 6 ] [ c ] = 1 num[6][c]=1 num[6][c]=1表示,位置5c出现了1次,用 n u m [ 5 ] [ c ] = 1 num[5][c]=1 num[5][c]=1表示,位置3c出现了一次,用 n u m [ 3 ] [ c ] = 1 num[3][c]=1 num[3][c]=1表示,其余位置 n u m [ 1 , 2 , 4 ] [ c ] = 1 num[1,2,4][c]=1 num[1,2,4][c]=1都是0。那么求位置4后面包括位置4在内c出现的次数,应该是位置6的c累加上位置5的c,即 n u m [ 5 ] [ c ] + n u m [ 6 ] [ c ] num[5][c]+num[6][c] num[5][c]+num[6][c],求位置1后面c出现的次数,应该是 n u m [ 2 ] [ c ] + n u m [ 3 ] [ c ] + n u m [ 4 ] [ c ] + n u m [ 5 ] [ c ] + n u m [ 6 ] [ c ] = 0 + 1 + 0 + 1 + 1 = 3 num[2][c]+num[3][c]+num[4][c]+num[5][c]+num[6][c]=0+1+0+1+1=3 num[2][c]+num[3][c]+num[4][c]+num[5][c]+num[6][c]=0+1+0+1+1=3。这里其实就是前缀和数组或者说是后缀和数组,因为求的是后面的值累加的结果。

综上,我们用 n u m s [ i ] [ c ] nums[i][c] nums[i][c]表示下标为i的位置的右边字符c出现的总次数。这里的数组就是后缀和数组。即 n u m s [ i ] [ c ] = n u m [ i + 1 ] [ c ] + n u m [ i + 2 ] [ c ] + . . . + n u m [ n ] [ c ] nums[i][c]=num[i+1][c]+num[i+2][c]+...+num[n][c] nums[i][c]=num[i+1][c]+num[i+2][c]+...+num[n][c]

那么 n u m s [ i ] [ c ] = n u m s [ i + 1 ] [ c ] + n u m [ i ] [ c ] nums[i][c]=nums[i+1][c]+num[i][c] nums[i][c]=nums[i+1][c]+num[i][c]

题目代码
import java.util.Scanner;
public class abb {
public static void main(String[] args) {
	Scanner scanner = new Scanner(System.in);
	int n = scanner.nextInt();
	char[] s = (" "+scanner.next()).toCharArray();
	int pre[][] = new int[n+2][26];
	for(int i = n;i >= 1;i--) {
		for(int j = 0;j < 26;j++) {
            //求下标为i的位置包括下标i在内26个字母中,每个字母出现的次数。这里要用到前缀和
			pre[i][j] =pre[i+1][j];
		}
		pre[i][s[i]-'a']++;//这里就是加上位置i的字母
	}
	long sum = 0;
	for(int i = 1;i <= n;i++) {
		for(int j = 0;j < 26;j++) {
            //注意这里要有j!=s[i]-'a'的判断,因为aaa是不合法的
            //同样也要有pre[i][j]>=2的判断,因为后面至少要有两个才能组合出acc
            //pre[i+1][j]是i+1,因为pre[i][j]包含了位置i的字母,但是我们求的是i后面的字母
            //但其实用pre[i][j]也没有问题,因为这里的字母j肯定和位置i的字母不一样,那么必然不会对pre[i][j]数组产生作用,因为这里的num[i][j]=0
			if(pre[i][j]>=2&&j!=s[i]-'a') sum += (pre[i+1][j]-1)*pre[i
+1][j]/2;
		}
	}
	System.out.println(sum);
}
}
鼠鼠我鸭

题目描述

在一个叫做酱西功爷枝叶鸡树学院的地方有n只小动物,要么是鼠鼠,要么是鸭鸭,从1到n编号,每只小动物有个体重 a i a_i ai

在这个学校里,存在一种神奇的魔法,可以将编号位于某个区间 [ l , r ] [l,r] [l,r]内的所有鼠鼠都变为鸭鸭,鸭鸭都变为鼠鼠(魔法并不会改变体重)。

现在你可以施放这个魔法至多1次。(也可以不施放)

问最终鸭鸭的总重量最多是多少?

输入格式

第一行一个整数T表示样例个数。 ( 1 ≤ T ≤ 10 ) (1≤T≤10) (1T10)

对于每个样例:

第一行一个整数n表示小动物的个数。( 1 ≤ n ≤ 1 0 5 1≤n≤10^5 1n105)

第二行 n n n个整数,表示第 i i i个小动物的类型。0表示鼠鼠,1表示鸭鸭。

第三行 n n n个整数,表示第 i i i个小动物的体重 a i a_i ai。( 1 ≤ a i ≤ 1 0 9 1≤a_i≤10^9 1ai109)

输出格式

对于每个样例一行一个整数表示答案。

样例输入

2
3
0 0 0
1 2 3
4
0 1 0 0
2 5 6 5

样例输出

6
16
题目分析

假设原本所有鸭鸭的重量是sum,操作后形成的偏移是fix,即经过至多1次操作后鸭鸭的总重量是sum+fix,这里的fix最小是0,因为如果操作后的fix是负数,会使得鸭鸭的总重量减少,倒不如不操作,直接是sum就可以了。

来看这个fix应该怎么求。以样例的第二组数据为例,如果操作区间是[0,4],那么每个位置对应的偏移量分别为2,-5,6,5。总的偏移量为2-5+6+5=8。如果操作区间是[1,2],总的偏移量为-5+6=1。其实要求某个区间的偏移量就是数组[2,-5,6,5]对应区间的区间和。这里的[2,-5,6,5]也叫做偏移量数组,因为对于位置i的值而言,如果他是鸭鸭,一次操作后就变为了鼠鼠,那么之前累加上的他的重量应该减去,所以偏移量就是负的该位置的重量也就是-a[i],如果他是鼠鼠,一次操作后就变为了鸭鸭,他的重量应该累加上,所以偏移量就是该位置的重量也就是a[i]。所以我们可以求一下偏移量数组的前缀和,然后利用前缀和求最大的偏移量区间和,也就是一开始说的fix,累加到原始的重量和sum里面就好。

假设偏移量的前缀和数组是pre[i],那么偏移量的区间和[l,r]就用pre[r]-pre[l-1],如果我们遍历l和r的话,双层嵌套for循环会超时,所以这里应该采用类似双指针的做法,假设固定了r,要想pre[r]-pre[l-1]最大,需要pre[l-1]是区间[1,l-1]里面最小的那个数,用mi表示,关键代码如下,

fix=0;mi=0;
for(int i=1;i<=n;i++)  
		{
			fix=max(fix,s[i]-mi);//i固定时,mi是下标比i小的数中的最小值
			mi=min(mi,s[i]);
		}

fix最小是0,所以初始化为0。这里的mi最小值也为0,mi为0时表示的是区间[1,i]的区间和,如果mi不为负数,说明s[i]-mi会变小,即比s[i]本身小,倒不如直接用s[i],s[i]表示的就是前i项之和,也是区间和。

题目代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N=1e5+10;
ll g[N],w[N],s[N],p[N];
ll sum,fix,mi;

int main(){
    int t;cin>>t;
    while(t--){
        int n;cin>>n;
        for(int i=1;i<=n;i++)cin>>g[i];
        for(int i=1;i<=n;i++)cin>>w[i];
        for(int i=1;i<=n;i++)
		{
			s[i]=s[i-1]+(g[i] == 1 ? -1 : 1)*w[i]; //计算出施加魔法后的偏移值(鸭子重量),如果原来是1(鸭子)就要减去,原来是0(鼠)就加上
		}
		sum=0;
        for(int i=1;i<=n;i++) {
            sum+=w[i]*g[i];
        }
        fix=0,mi=0;
        for(int i=1;i<=n;i++)
		{
			fix=max(fix,s[i]-mi);
			mi=min(mi,s[i]);
		}

        cout<<sum+fix<<'\n';
    }

    return 0;
}

代码有一个易错点,因为变量都是全局变量,所以sum,fix,e在每一组测试样例中都要重置为初始值。

import java.util.Scanner;
public class Main{


	static  int N=(int) (1e5+10);
	static long[] g=new long[N],w=new long[N],s=new long[N],p=new long[N];
	static long sum,fix,mi;
public static void main(String[] args) {
	 int t;
	 Scanner scanner = new Scanner(System.in);
	 t = scanner.nextInt();
	    while(t-- > 0){
	        int n;
	        n = scanner.nextInt();
	        for(int i=1;i<=n;i++)g[i]=scanner.nextLong();
	        for(int i=1;i<=n;i++)w[i]=scanner.nextLong();
	        for(int i=1;i<=n;i++)
			{
				s[i]=s[i-1]+(g[i] == 1 ? -1 : 1)*w[i]; //计算出施加魔法后的偏移值(鸭子重量),如果原来是1(鸭子)就要减去,原来是0(鼠)就加上
			}
			sum=0;
	        for(int i=1;i<=n;i++) {
	            sum+=w[i]*g[i];
	        }
	        fix=0;mi=0;
	        for(int i=1;i<=n;i++)  //从第一个遍历到最后,计算出最大最小值
			{
				fix=Math.max(fix,s[i]-mi);
				mi=Math.min(mi,s[i]);
			}
            System.out.println(sum+fix);
	    }

}
}

如果题目分析有错误或者没有表达清楚的地方,欢迎在评论区里指出!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1462652.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PotPlayer+Alist挂载并播放网盘视频

文章目录 说明技术WebDAVPotPlayer 操作步骤一&#xff1a;Alist开启WebDAV代理二&#xff1a;PotPlayer连接Alist 说明 Alist网页端播放视频受限&#xff0c;主要是文件大于20MB&#xff0c;由于官方限制&#xff0c;无法播放需要使用user-agent修改插件&#xff0c;设置百度…

ES项目应用

配置: ES存储了2-3亿条&#xff0c;几百GB ES集群有5 个节点 2主2副 ES返回数据量窗口大小设置 index.max_result_window 深度翻页 1.from size 方式 2.scroll相当于维护了一份当前索引段的快照信息&#xff0c;这个快照信息是你执行这个scroll查询时的快照。在这个查询后的任…

【selenium】八大元素定位方式|xpath css id name...

目录 一、基础元素定位 二、cssSelector元素定位——通过元素属性定位 三、xpath元素定位——通过路径 1 、xpath绝对定位 &#xff08;用的不多&#xff09; 缺点&#xff1a;一旦页面结构发生变化&#xff08;比如重新设计时&#xff0c;路径少两节&#xff09;&#x…

跨境电商营销推广:法律合规指引与风险管理策略

在全球数字化时代&#xff0c;跨境电商正成为国际贸易的重要组成部分。然而&#xff0c;在跨境电商的营销推广过程中&#xff0c;合规问题不容忽视。为了避免法律纠纷&#xff0c;企业需要了解并遵守各国的法律法规。本文将深入探讨跨境电商在营销推广中需要遵守的法律法规&…

Android 面试问题 2024 版(其二)

Android 面试问题 2024 版&#xff08;其二&#xff09; 六、多线程和并发七、性能优化八、测试九、安全十、Material设计和 **UX/UI** 六、多线程和并发 Android 中的进程和线程有什么区别&#xff1f; 答&#xff1a;进程是在自己的内存空间中运行的应用程序的单独实例&…

数据分析(二)自动生成分析报告

1. 报告生成思路概述 怎么快速一份简单的数据分析报告&#xff0c;注意这个报告的特点&#xff1a; --网页版&#xff0c;可以支持在线观看或者分享HTML文件 --标题&#xff0c;动图&#xff0c;原始数据应有尽有 --支持交互&#xff0c;比如plotly交互画面&#xff0c;数据…

leetcode hot100单词拆分

在本题中&#xff0c;我们是要把一个字符串&#xff0c;判断是否能用给的字符串数组中的单词进行拆分&#xff0c;如果可以则返回true&#xff0c;不能的话则返回false。这个题一开始看无法与背包问题联系在一起。但仔细考虑&#xff0c;就是用物品&#xff08;给的字符串数组中…

运维的利器–监控–zabbix–第二步:建设–部署zabbix agent

文章目录 监控客户端部署及添加主机一、在 zabbix-server 安装客户端二、在本机和其他linux主机安装zabbix agent客户端1、安装2、配置3、启动并开机自启4、添加主机创建主机组创建主机等一会或重启zabbix-server查看配置是否成功 三、在其他windows上安装zabbix agent客户端下…

用于扫描机密的开源解决方案

TruffleHog 最初是在 2016 年独立创作的一个研究工具。当发布它时&#xff0c;没有工具扫描 Git 修订历史记录以获取秘密。我的预感是旧版本的代码中隐藏着很多秘密&#xff0c;但没有工具可以查找它们。 我的预感是对的。该工具迅速流行并变得非常流行。如今&#xff0c;它在…

贝叶斯统计——入门级笔记

绪论 1.1 引言 全概率公式 贝叶斯公式 三种信息 总体信息 当把样本视为随机变量时&#xff0c;它有概率分布&#xff0c;称为总体分布&#xff0e; 如果我们已经知道总体的分布形式这就给了我们一种信息&#xff0c;称为总体信息 样本信息 从总体中抽取的样本所提供的信息 先…

公共用例库计划--个人版(八)pyinstaller打包pyqt6,从168 MB到40.2 MB

1、任务概述 本次计划的核心任务是开发一个&#xff0c;个人版的公共用例库&#xff0c;旨在将各系统和各类测试场景下的通用、基础以及关键功能的测试用例进行系统性地归纳整理&#xff0c;并以提高用例的复用率为目标&#xff0c;力求最大限度地减少重复劳动&#xff0c;提升…

Maven私服搭建Nexus3

第一部分&#xff1a;仓库部署 下载地址&#xff1a;https://help.sonatype.com/en/download.html 备用下载链接&#xff0c;部分已经失效了 解压后会有两个文件夹&#xff1a; nexus-3.20.1-01 sonatype-work 访问地址配置路径 \nexus-3.20.1-01\bin\nexus.vmoptions -Xms1…

企业为何选择芯片运营管理ERP?

随着科技的飞速发展和市场竞争的加剧&#xff0c;企业对于运营管理的需求也日益增强。在这一背景下&#xff0c;越来越多的企业开始选择芯片运营管理ERP(企业资源规划)系统&#xff0c;以提升自身的运营效率和竞争力。那么&#xff0c;企业为何选择芯片运营管理ERP呢? 芯片运营…

【快速上手QT】04-定时器Timer

先来个小示例 我们先简单的来触发一下定时器。 #include "Zhetu.h"#include <qdebug.h>void Zhetu::timerEvent(QTimerEvent* event) { //定时器触发函数qDebug() << "Hello world"; }Zhetu::Zhetu(QWidget *parent): QMainWindow(parent){t…

实现可拖拽的页面元素排序更新数据库排序

摘要&#xff1a; 拖拽列表改变路边排序&#xff0c;并且更新后台数据库列表的排序&#xff0c;重新请求的时候获取拖拽后的排序&#xff01; Layui&#xff1a; // 拖拽内页顺序list document.querySelector(#view_side_tab);// 创建cruentItem存放将要拖动的元素let cruen…

JUC并发编程学习与实践

文章目录 学习资料创建和运行线程方法一&#xff1a;直接使用Thread方法二&#xff1a;使用Runnable配合Thread方法三&#xff1a;FutureTask配合Thread 线程的常见方法start与runsleep与yield线程的优先级 join方法详解interrupt线程打断interrupt线程打断后&#xff0c;线程不…

【成都游戏业:千游研发之都的发展与机遇】

成都游戏业&#xff1a; 千游研发之都的发展与机遇 作为我国西部游戏产业的龙头&#xff0c;成都这座城市正在高速发展&#xff0c;目标是崛起成为千亿级游戏研发之都。多年来&#xff0c;在政策扶持、人才汇聚以及文化底蕴等助力下&#xff0c;成都游戏业已经形成完整的产业链…

SAP MIGO发货过账的时候批次库存确定:事务码MBC1进行激活即可

事务码&#xff1a; MBC1 ~ MBC3 使用MBC1按照工厂层级进行激活 接下来MIGO发货过账的时候就可以使用批次库存确定了&#xff0c;点击下图中圈出来的库存确定按钮

Spring AOP 实现原理详解之 JDK 动态代理

目录 一. 前言 二. JDK 代理的示例 2.1. 不需要 Maven 依赖 2.2. 定义实体 2.3. 被代理的类和接口 2.4. JDK 代理类 2.5. 使用代理 三. JDK 代理的流程 3.1. ProxyGenerator 生成代码 3.2. 从生成的 Proxy 代码看执行流程 四. Spring AOP 中 JDK代理的实现 4.1. Sp…

【虚拟仿真】Unity3D中实现3DUI,并且实现Button、InputField、Toggle等事件绑定

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 一、前言 最近在项目中需要用到3DUI的展示,之前一般会用TextMeshPro进行展示: 但是,后面又需要添加按钮、Toggle等…