1. 问题描述:
给定一个长度为 n 的整数序列 a1,a2,…,an,请你找到一个该序列的子序列,要求:
- 该子序列的所有元素之和必须是奇数。
- 在满足条件 1 的前提下,该子序列的所有元素之和应尽可能大。
输出你找到的满足条件的子序列的所有元素之和。保证至少存在一个满足条件的子序列。注意,子序列不一定连续。
输入格式
第一行包含一个整数 n。第二行包含 n 个整数 a1,a2,…,an。
输出格式
输出一个整数,表示满足条件的子序列的所有元素之和。
数据范围
前 6 个测试点满足 1 ≤ n ≤ 5
所有测试点满足 1 ≤ n ≤ 10 ^ 5,−10 ^ 4 ≤ ai ≤ 10 ^ 4
输入样例1:
4
-2 2 -3 1
输出样例1:
3
输入样例2:
3
2 -5 -3
输出样例2:
-1
来源:https://www.acwing.com/problem/content/description/4417/
2. 思路分析:
分析题目可以知道第二个条件比较好处理所以我们可以先考虑第二个条件,因为需要使得和最大所以可以使用一个变量 s 来记录 a 中所有大于 0 的元素之和,如果 s 恰好为奇数那么很好满足了第一个条件所以当前的 s 就是答案,如果为偶数那么不满足第一个条件,所以问题的关键是当 s 为偶数的时候如何处理,当 s 为偶数的时候那么 s 肯定是由偶数个正奇数组成,要想使得 s 为奇数那么分为两种情况(奇偶性只需要看正奇数的个数即可):第一种情况是 s 减去一个已经加上的最小的正奇数,第二种情况是加上一个最大的负奇数这样才可以使得 s 是最大的,加上和减去一个负数都可以使得 s 由偶数变为奇数,两种情况取一个 max 就是答案,我们可以在遍历数组 a 的时候使用 odd_pos 和 odd_even 来记录正的奇数和负的奇数,最后对 odd_pos 从小到大排序,odd_even 从大到小排序,在两种情况取一个 max 就是答案。
3. 代码如下:
python:
class Solution:
def process(self):
n = int(input())
a = list(map(int, input().split()))
s = 0
INF = 10 ** 10
# odd_pos和odd_neg记录正的奇数和负的奇数
odd_pos, odd_neg = list(), list()
for x in a:
if x & 1:
# x & 1 == 1 表示 x 是奇数否则为偶数
if x > 0:
odd_pos.append(x)
else:
odd_neg.append(x)
if x > 0:
s += x
# 说明当前所有正数之和为奇数所以当前的s为最大
if s & 1:
print(s)
else:
# 考虑去掉一个正的奇数或者加上一个负的奇数这两种情况, 两种情况取一个max就是答案
odd_pos.sort()
odd_neg.sort(reverse=True)
res = -INF
if len(odd_pos):
res = s - odd_pos[0]
if len(odd_neg):
res = max(res, s + odd_neg[0])
print(res)
if __name__ == '__main__':
Solution().process()
我们只关心最大的负奇数和最小的正奇数,所以使用两个变量odd_pos 和 odd_neg 来维护即可,这样可以不用存储所有的正奇数和负奇数,省略了排序的步骤:
class Solution:
def process(self):
n = int(input())
a = list(map(int, input().split()))
s = 0
INF = 10 ** 10
odd_pos, odd_neg = INF, -INF
for x in a:
if x & 1:
if x > 0:
odd_pos = min(odd_pos, x)
elif x < 0:
odd_neg = max(odd_neg, x)
if x > 0:
s += x
if s & 1:
print(s)
else:
res = -INF
if odd_pos != INF:
res = s - odd_pos
if odd_neg != -INF:
res = max(res, s + odd_neg)
print(res)
if __name__ == '__main__':
Solution().process()
go:
package main
import (
"bufio"
"fmt"
"io"
"os"
"sort"
)
func max(a, b int) int {
if a > b {
return a
}
return b
}
func run(r io.Reader, w io.Writer) {
in := bufio.NewReader(r)
out := bufio.NewWriter(w)
defer out.Flush()
var n, x int
fmt.Fscan(in, &n)
var odd_pos, odd_neg []int
s := 0
for i := 0; i < n; i++ {
fmt.Fscan(in, &x)
if x&1 == 1 {
if x > 0 {
odd_pos = append(odd_pos, x)
} else {
odd_neg = append(odd_neg, x)
}
}
if x > 0 {
s += x
}
}
INF := 10000000000
if s&1 == 1 {
fmt.Fprintln(out, s)
} else {
res := -INF
sort.Ints(odd_pos)
sort.Sort(sort.Reverse(sort.IntSlice(odd_neg)))
if len(odd_pos) > 0 {
res = s - odd_pos[0]
}
if len(odd_neg) > 0 {
res = max(res, s+odd_neg[0])
}
fmt.Fprintln(out, res)
}
}
func main() {
run(os.Stdin, os.Stdout)
}