Codeforces Round #658 (Div. 2) - D. Unmerge(dp)
Posted zzzzzzy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #658 (Div. 2) - D. Unmerge(dp)相关的知识,希望对你有一定的参考价值。
题目链接:Unmerge
题意:定义两个数组的合并merge(a,b),每次将数组a第一个元素和数组b第一个元素中最小的那个放到数组c中,同时删除那个最小的元素,现在给你一个长度为2*n的排列,问是否能由两个长度为n的数组合并而成
思路:对于长度为2*n的排列,显然是通过一段一段合并得到的,例如(3,2,6,1,5,7,8,4),找到3后面比他大的第一个数6,6后面比他大的第一个数7,7后面比他大的第一个数8,应该分为(3,2),(6,1,5),(7),(8,4)这四段,然后将这四段进行分配,判断能够组成两个长度为n的数组,用01背包判断(背包容量为n,物品的容量和价值都为每一段的长度),判断最后的最大价值是否为n即可
#include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #include <vector> using namespace std; typedef long long ll; const int N = 4010; const int INF = 0x3f3f3f3f; int T, n, cnt, a[N], d[N], dp[N]; vector<int> p; int main() { // freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); scanf("%d", &T); while (T--) { cnt = 0; p.clear(); scanf("%d", &n); for (int i = 1; i <= 2 * n; i++) scanf("%d", &a[i]); int imax = 0; for (int i = 1; i <= 2 * n; i++) { if (a[i] < imax) continue; imax = a[i]; p.push_back(i); } p.push_back(2 * n + 1); for (int i = 1; i < p.size(); i++) d[++cnt] = p[i] - p[i - 1]; for (int i = 1; i <= n; i++) dp[i] = -INF; for (int i = 1; i <= cnt; i++) for (int k = n; k >= d[i]; k--) dp[k] = max(dp[k], dp[k - d[i]] + d[i]); printf(n == dp[n] ? "YES " : "NO "); } return 0; }
以上是关于Codeforces Round #658 (Div. 2) - D. Unmerge(dp)的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #658 (Div. 2) [补题记录]
Codeforces Round #658 (Div. 2)ABC2
Codeforces Round #658 (Div. 2) D. Unmerge(dp)
Codeforces Round #658 (Div. 2) - D. Unmerge(dp)