题目描述与示例
题目描述
小红有一个长度为n
的数组a
,她将对数组进行m
次操作,每次操作有两种类型:
- 将数组中所有值为奇数的元素加上
x
- 将数组中所有值为偶数的元素加上
x
请你输出m
次操作后的数组
输入描述
第一行两个整数n
和m
,表示数组长度和操作次数
第二行n
个整数,表示数组a
的初始值。
接下来m
行,每行两个整数t
和x
,t
表示一次操作的类型和参数,t
为1
表示第一种操作,t
为2
表示第二种操作
1 < n, m < 10^5
1 < ai, x < 10^5
1 <= t <= 2
输出描述
输出一行,包含n
个整数,表示m
次操作后的数组
示例
输入
5 3
1 2 3 4 5
1 2
2 2
1 3
输出
6 4 8 6 10
说明
第一次,将所有奇数元素加 2
,数组变为[3,2,5,4,7]
第二次,将所有偶数元素加 2
,数组变为[3,4,5,6,7]
第三次,将所有奇数元素加 3
,数组变为[6,4,8,6,10]
时空限制
时间限制: C/C++ 1000MS,其他语言 2000MS
内存****限制: C/C++ 256M,其他语言 512M
解题思路
注意到一个非常重要的数学性质,对于任意两个正整数相加
奇数 + 奇数 = 偶数
偶数 + 偶数 = 偶数
奇数 + 偶数 = 奇数
偶数 + 奇数 = 奇数
假设一开始数组中既存在奇数,也存在偶数。在遇到第一个为奇数的x
时,若
t = 1
,则数组中所有的奇数都要加上x
,相加完毕后所有元素都变成偶数t = 2
,则数组中所有的偶数都要加上x
,相加完毕后所有元素都变成奇数
我们分别用isAllOdd
和isAllEven
两个变量来表示数组的状态。当
isAllOdd
和isAllEven
均为False
时,说明此时数组中既存在奇数,也存在偶数。isAllOdd = True
,此时数组中的元素均为奇数isAllEven = True
,此时数组中的元素均为偶数- 注意:不可能出现
isAllOdd
和isAllEven
均为True
的情况。
设置两个变量oddx
和evenx
,分别表示初始数组中的奇数和偶数,在m
次操作中的增量。那么在遍历过程中,所有元素的变化可以依照下表进行
x是奇数 | x是偶数 | ||
---|---|---|---|
t=1数组所有奇数加x | 数组中有奇数有偶数isAllEven == False and isAllOdd == False | oddx += x 所有的奇数变为偶数isAllEven = True | oddx += x 数组的奇偶性不变 |
数组中只有奇数isAllOdd == True | oddx += x``evenx += x 数组的奇偶性反过来isAllEven = not isAllEven``isAllOdd = not isAllOdd | oddx += x``evenx += x 数组的奇偶性不变 | |
数组中只有偶数isAllEven == True | 不做任何处理 | ||
t=2数组所有偶数加x | 数组中有奇数有偶数isAllEven == False and isAllOdd == False | evenx += x 所有的偶数变为奇数isAllOdd = True | evenx += x 数组的奇偶性不变 |
数组中只有偶数isAllEven == True | oddx += x``evenx += x 数组的奇偶性反过来isAllEven = not isAllEven``isAllOdd = not isAllOdd | oddx += x``evenx += x 数组的奇偶性不变 | |
数组中只有奇数isAllOdd == True | 不做任何处理 |
代码
Python
n, m = map(int, input().split())
a = list(map(int, input().split()))oddx = 0
evenx = 0
isAllOdd = False
isAllEven = Falsefor _ in range(m):t, x = map(int, input().split())# x为奇数的情况if x % 2 == 1:# 若此时数组中同时存在偶数和奇数if isAllEven == False and isAllOdd == False:# 若是操作1,数组中所有奇数加上xif t == 1:oddx += x# 数组中所有的元素都变成偶数isAllEven = True# 若是操作2,数组中所有偶数加上xelif t == 2:evenx += x# 数组中所有的元素都变成奇数isAllOdd = True# 已经是全偶数或全奇数的情况,变号elif (isAllEven and t == 2) or (isAllOdd and t == 1):oddx += xevenx += xisAllEven = not isAllEvenisAllOdd = not isAllOdd# x为偶数的情况else:# 若此时数组中同时存在偶数和奇数if isAllEven == False and isAllOdd == False:# 若是操作1,数组中所有奇数加上xif t == 1:oddx += x# 若是操作2,数组中所有偶数加上xelse:evenx += x# 已经是全偶数或全奇数的情况,不变号elif (isAllEven and t == 2) or (isAllOdd and t == 1):oddx += xevenx += x# 遍历原数组,所有奇数加上oddx,所有偶数加上evenx
ans = [a[i] + oddx if a[i] % 2 == 1 else a[i] + evenx for i in range(n)]
print(" ".join(map(str, ans)))
Java
import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();int m = sc.nextInt();int[] a = new int[n];for (int i = 0; i < n; i++) {a[i] = sc.nextInt();}int oddx = 0;int evenx = 0;boolean isAllOdd = false;boolean isAllEven = false;for (int i = 0; i < m; i++) {int t = sc.nextInt();int x = sc.nextInt();if (x % 2 == 1) {if (!isAllEven && !isAllOdd) {if (t == 1) {oddx += x;isAllEven = true;} else if (t == 2) {evenx += x;isAllOdd = true;}} else if ((isAllEven && t == 2) || (isAllOdd && t == 1)) {oddx += x;evenx += x;isAllEven = !isAllEven;isAllOdd = !isAllOdd;}} else {if (!isAllEven && !isAllOdd) {if (t == 1) {oddx += x;} else {evenx += x;}} else if ((isAllEven && t == 2) || (isAllOdd && t == 1)) {oddx += x;evenx += x;}}}int[] ans = new int[n];for (int i = 0; i < n; i++) {if (a[i] % 2 == 1) {ans[i] = a[i] + oddx;} else {ans[i] = a[i] + evenx;}}for (int i = 0; i < n; i++) {if (i < n - 1) {System.out.print(ans[i] + " ");} else {System.out.println(ans[i]);}}}
}
C++
#include <iostream>
#include <vector>using namespace std;int main() {int n, m;cin >> n >> m;vector<int> a(n);for (int i = 0; i < n; i++) {cin >> a[i];}int oddx = 0;int evenx = 0;bool isAllOdd = false;bool isAllEven = false;for (int i = 0; i < m; i++) {int t, x;cin >> t >> x;if (x % 2 == 1) {if (!isAllEven && !isAllOdd) {if (t == 1) {oddx += x;isAllEven = true;} else if (t == 2) {evenx += x;isAllOdd = true;}} else if ((isAllEven && t == 2) || (isAllOdd && t == 1)) {oddx += x;evenx += x;isAllEven = !isAllEven;isAllOdd = !isAllOdd;}} else {if (!isAllEven && !isAllOdd) {if (t == 1) {oddx += x;} else {evenx += x;}} else if ((isAllEven && t == 2) || (isAllOdd && t == 1)) {oddx += x;evenx += x;}}}vector<int> ans(n);for (int i = 0; i < n; i++) {if (a[i] % 2 == 1) {ans[i] = a[i] + oddx;} else {ans[i] = a[i] + evenx;}}for (int i = 0; i < n; i++) {if (i < n - 1) {cout << ans[i] << " ";} else {cout << ans[i] << endl;}}return 0;
}
时空复杂度
时间复杂度:O(m+n)
。一共有m
次操作,最后修改数组需要遍历n
个元素。
空间复杂度:O(1)
。仅需若干常数变量
华为OD算法/大厂面试高频题算法练习冲刺训练
-
华为OD算法/大厂面试高频题算法冲刺训练目前开始常态化报名!目前已服务100+同学成功上岸!
-
课程讲师为全网50w+粉丝编程博主@吴师兄学算法 以及小红书头部编程博主@闭着眼睛学数理化
-
每期人数维持在20人内,保证能够最大限度地满足到每一个同学的需求,达到和1v1同样的学习效果!
-
60+天陪伴式学习,40+直播课时,300+动画图解视频,300+LeetCode经典题,200+华为OD真题/大厂真题,还有简历修改、模拟面试、专属HR对接将为你解锁
-
可上全网独家的欧弟OJ系统练习华子OD、大厂真题
-
可查看链接 OD算法冲刺训练课程表 & OD真题汇总(持续更新)
-
绿色聊天软件戳
od1336
了解更多