Codeforces Round #575 (Div. 3) 1196B. Odd Sum Segments 数学思维

B. Odd Sum Segments
time limit per test3 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
You are given an array a consisting of n integers a1,a2,…,an. You want to split it into exactly k non-empty non-intersecting subsegments such that each subsegment has odd sum (i. e. for each subsegment, the sum of all elements that belong to this subsegment is odd). It is impossible to rearrange (shuffle) the elements of a given array. Each of the n elements of the array a must belong to exactly one of the k subsegments.

Let’s see some examples of dividing the array of length 5 into 3 subsegments (not necessarily with odd sums): [1,2,3,4,5] is the initial array, then all possible ways to divide it into 3 non-empty non-intersecting subsegments are described below:

[1],[2],[3,4,5];
[1],[2,3],[4,5];
[1],[2,3,4],[5];
[1,2],[3],[4,5];
[1,2],[3,4],[5];
[1,2,3],[4],[5].
Of course, it can be impossible to divide the initial array into exactly k subsegments in such a way that each of them will have odd sum of elements. In this case print “NO”. Otherwise, print “YES” and any possible division of the array. See the output format for the detailed explanation.

You have to answer q independent queries.

Input
The first line contains one integer q (1≤q≤2⋅105) — the number of queries. Then q queries follow.

The first line of the query contains two integers n and k (1≤k≤n≤2⋅105) — the number of elements in the array and the number of subsegments, respectively.

The second line of the query contains n integers a1,a2,…,an (1≤ai≤109), where ai is the i-th element of a.

It is guaranteed that the sum of n over all queries does not exceed 2⋅105 (∑n≤2⋅105).

Output
For each query, print the answer to it. If it is impossible to divide the initial array into exactly k subsegments in such a way that each of them will have odd sum of elements, print “NO” in the first line. Otherwise, print “YES” in the first line and any possible division of the array in the second line. The division can be represented as k integers r1, r2, …, rk such that 1≤r1<r2<⋯<rk=n, where rj is the right border of the j-th segment (the index of the last element that belongs to the j-th segment), so the array is divided into subsegments [1;r1],[r1+1;r2],[r2+1,r3],…,[rk−1+1,n]. Note that rk is always n but you should print it anyway.

Example
inputCopy
3
5 3
7 18 3 14 1
5 4
1 2 3 4 5
6 2
1 2 8 4 10 2
outputCopy
YES
1 3 5
NO
NO


题目大意:求数组n分成k个区间,且每个区间和为奇数。
一个数学思维题:奇数+奇数=偶数,偶数+偶数=奇数,偶数+奇数=奇数
首先判断YES的条件我们很容易想到,每个区间必须有一个奇数,那么满足的条件为数组中奇数的个数>=k
那是不是满足该条件一定是YES呢?
并不是,在奇数个数>=k的条件下,每个区间必有一个奇数,偶数的数量和分布在哪个区间都不影响区间和为奇数,那么会多出(奇数个数-k)个奇数,那么这些奇数如何安排呢?
现在每个区间和都是奇数,如果对于某个区间,我们再放入m个奇数

  1. m为奇数,那么该区间奇数+奇数x奇数(奇数)=偶数,不满足条件
  2. m为偶数,那么该区间奇数+偶数×奇数(偶数)=奇数,满足条件

所以多出来的奇数必须满足(奇数个数-k)为偶数个,所以满足以上两个条件就可以得出YES,那么如何输出右边界呢
我们可以按照每个奇数在原数组的位置作为右边界,分好k-1个区间后,以n为最后一个区间的右边界。这样就是前k-1个区间每个区间一个奇数,最后一个区间包含奇数个奇数。

#include <cstdio>
const int MAXN = 2e5 + 10;
int a[MAXN], b[MAXN];
int main()
{
	int q, n, k, cnt;
	scanf("%d", &q);
	for (int i = 0; i < q; ++i)
	{
		cnt = 0;
		scanf("%d%d", &n, &k);
		for (int i = 0; i < n; ++i)
		{
			scanf("%d", &a[i]);
			//记录数组中奇数元素
			if (a[i] & 1)
			{
				b[cnt++] = i + 1;
			}
		}
		//判断是否有解的条件
		if (cnt >= k && (cnt - k + 1) & 1)
		{
			printf("YES\n");
			for (int i = 0; i < k - 1; ++i)
			{
				printf("%d ", b[i]);
			}
			printf("%d\n", n);
		}
		else
		{
			printf("NO\n");
		}
	}
	return 0;
}
发布了51 篇原创文章 · 获赞 19 · 访问量 8303

猜你喜欢

转载自blog.csdn.net/WxqHUT/article/details/98168146