Atcoder abc162 F Select Half题解

F - Select Half


Time Limit: 2 sec / Memory Limit: 1024 MB

Score : 600 points

Problem Statement

Given is an integer sequence A1,...,Aof length N.

We will choose exactly N/2 elements from this sequence so that no two adjacent elements are chosen.

Find the maximum possible sum of the chosen elements.

Here xdenotes the greatest integer not greater than x.

Constraints

  • 2N2×1052≤N≤2×105
  • |Ai|109|Ai|≤109
  • All values in input are integers.

Input

Input is given from Standard Input in the following format:

NN
A1A1 ...... ANAN

Output

Print the maximum possible sum of the chosen elements.


Sample Input 1 

6
1 2 3 4 5 6

Sample Output 1 

12

Choosing 2244, and 66 makes the sum 1212, which is the maximum possible value.


Sample Input 2 

5
-1000 -100 -10 0 10

Sample Output 2 

0

Choosing 10−10 and 1010 makes the sum 00, which is the maximum possible value.


Sample Input 3 Copy

Copy
10
1000000000 1000000000 1000000000 1000000000 1000000000 1000000000 1000000000 1000000000 1000000000 1000000000

Sample Output 3 

Copy
5000000000

Watch out for overflow.


Sample Input 4 

27
18 -28 18 28 -45 90 -45 23 -53 60 28 -74 -71 35 -26 -62 49 -77 57 24 -70 -93 69 -99 59 57 -49

Sample Output 4 

295
这道题其实并不难,但是难想出来。题意很简单,就是给一堆数字,选取其中的n/2,选的数字不能相邻,问最大的和,一眼确实能想到使用dp来写,但是就是不知到怎么写,参考了网上大神的博客,采用一维DP在复杂度O(n)来解决此问题。
我们先设立一维dp数组dp[i]代表当考虑前i个组成的子序列且取了i/2个不相邻的数字的时候的最大值,我们考虑两种情况:
1)i为奇数,i&1 == 1,那么我们知道有两种情况,一个是取第i个数,一个是不要它,如果我们取第i个数,那么我们肯定不能考虑在dp[i-1]的情况推到到dp[i],因为万一dp[i-1]的最后一个取到了就不能取第i个了,所以我们应当是从前i-2个构成的取了(i-2)/2个构成的最大和中推到至从前i个取了i/2构成的最大和,也就是dp[i] = dp[i-2] + a[i]。如果不取第i个那就可以从dp[i-1]去推到了,因为你既然第i个不要,那么不久相当于前i-1个中取i/2个嘛(因为是奇数所以i/2==(i-1)/2)不就是dp[i-1]的含义🐎。
2)i为偶数,i&1 == 0,也是两种情况,取还是不取,因为取的话,肯定是从dp[i-2]推到dp[i],所以说dp[i] = dp[i-2] + a[i], 但如果不取的话,你想想,你是不是要在前i-1个中间找i/2个,注意,dp[i-1]代表从前i-1个中找(i-1)/2,当i为偶数时,i/2 == (i-1)/2 + 1,所以前i-1个要取一半多一个,想想,是不是只能全取前面的奇数,全取偶数势必因为第i个不要而导致个数只能是i/2-1个,不符合我们dp的要求,当然奇偶互着来更不可能,本来奇偶相邻的话就要间隔两个,但是我们i-1个连间隔一个都只能在全取奇数的情况下才能保证是i/2,所以只可能全取奇数,我们可以用一个前缀数组记录前i个中所有下标为奇数的数字之和sum(为了方便懒得计算,sum的所有偶数下标均为0),所以dp[i] = sum[i - 1];

        i&1 == 1, max(dp[i - 1], dp[i - 2] + a[i]);
因此dp[i] =
        i&1 == 0, max(sum[i - 1], dp[i - 2] + a[i]);
AC代码:
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3fffffff;
long long dp[200005];//注意dp的含义,代表前i个组成的序列中取不相邻的i/2个的最大和
long long a[200005];
long long sum[200005];
int main()
{
	int n;
	scanf("%d", &n);
	scanf("%lld", &a[1]);
	sum[1] = a[1];
	for(int i = 2; i <= n; i++)
	{
		scanf("%lld", &a[i]);
		if(i & 1)
			sum[i] = sum[i - 2] + a[i];//奇数前缀和 
	}
	dp[1] = 0;//1/2==0,所以dp[1] == 0
	for(int i = 2; i <= n; i++)
	{
		if(i & 1)
			dp[i] = max(dp[i - 2] + a[i], dp[i - 1]);
		else
			dp[i] = max(sum[i - 1], dp[i - 2] + a[i]);
	}
	printf("%lld", dp[n]);
	return 0;
}

  如果还是看不太懂,英文好的话可以康康原博客,需要科协上网:https://icode54.blogspot.com/p/dp-1-atcoder-beginner-contest-162.html

算了,手动copy吧:

ABC #162 F - Select Half

Problem Statement - here

 
Solution -> We will be using 1d DP to solve the problem. We will make the prefix sum array for odd positions beforehand. Let's denote it as ps[ ]. (eg -> ps[5] = ps[3] + a[5])
 
So, let's break the problem into 2 halves ->
  1. When the current index in consideration (i) is odd
  2. When i is even.

Case 01 - When i is even:

We need to choose exactly i/2 elements.
SO, dp[i] = max(dp[i-2]+a[i],ps[i-1]).
Let's understand the above line -
I have 2 choices for the current index:
  1. If i include current index in my answer, then the problem reduces to exactly i/2 - 1elements. This is nothing but (i-2)/2. So dp[i-2] comes into play.
  2. If I decide to leave my current index. Problem reduces to finding max of exactly i/2 elements in the range of [0,i-1] where (i-1)/2 < i/2. And also, there is exactly one sequence, that can give i/2 elements. This is 1,3,5,7,....i-1. So it is nothing but prefix sum of all odd positions up to i-1.

Case 02 - When i is odd:

This case is simple. Since i/2 is same as (i-1)/2, we can transform this as 
dp[i] = max(dp[i-1],a[i]+dp[i-2])
 
Let's understand this line.
dp[i-1] is fairly clear. It comes if I decide not to pick my current element. Then it is the same as a subproblem of size i-1. Because even in the subproblem of size i-1.  I need to pick exactly i/2 elements.
But, If I want to pick up my current element, the subproblem reduces to i-2. So a[i] + dp[i-2] comes into picture. This happens because, If i pick up an element, the problem reduces to exactly picking up i/2 - 1 more elements. This is nothing but (i-2)/2. So the problem reduces to dp[i-2].

posted @ 2020-04-22 18:08  funforever  阅读(337)  评论(0编辑  收藏  举报