Codeforces Round #658 (Div. 2)(D. Unmerge)
题目描述
Let aa and bb be two arrays of lengths nn and mm, respectively, with no elements in common. We can define a new array merge(a,b) of length n+mn+m recursively as follows:
- If one of the arrays is empty, the result is the other array. That is, merge(∅,b)=b and merge(a,∅)=a. In particular, merge(∅,∅)=∅.
- If both arrays are non-empty, and a1<b1, then merge(a,b)=[a1]+merge([a2,…,an],b). That is, we delete the first element a1 of a, merge the remaining arrays, then add a1 to the beginning of the result.
- If both arrays are non-empty, and a1>b1, then merge(a,b)=[b1]+merge(a,[b2,…,bm]). That is, we delete the first element b1 of b, merge the remaining arrays, then add b1 to the beginning of the result.
This algorithm has the nice property that if a and b are sorted, then merge(a,b) will also be sorted. For example, it is used as a subroutine in merge-sort. For this problem, however, we will consider the same procedure acting on non-sorted arrays as well. For example, if a=[3,1] and b=[2,4], then merge(a,b)=[2,3,1,4].
A permutation is an array consisting of nn distinct integers from 11 to nn in arbitrary order. For example, [2,3,1,5,4] is a permutation, but [1,2,2] is not a permutation (2 appears twice in the array) and [1,3,4] is also not a permutation (n=3 but there is 4 in the array).
There is a permutation p of length 2n. Determine if there exist two arrays a and b, each of length n and with no elements in common, so that p=merge(a,b).
题目大意:
给你一串长度为2n的数字,为你是否可以将这2n个数字分成两串长度为n的数字,设这两个数组为a,b,且通过merge(a,b)得到新数组等于原数组。其中merge操作就是将a , b 两个数组中首个数字的最小值拿出来放入新数组 。
思路:
首先可以将原数组分成若干个子串,再由这些子串去构成 a , b 这两个数组。由于那头部最小的,所以只要这个子串下面的数字比头部的小即可。因此子串可以这样分,如 {3 2 6 1 5 7 8 4},就分为{3 2} {6 1 5} {7} {8 4}即可,通过这些子串的合并就可以得到a b两个数组,因此,如果这些子串无法变成长度为n的两个数组,那么答案就是NO。
那么怎么确定是否可以构成长度为n的数组,可以用01背包来确定是否可行。将背包的权值和体积都设为长度。
代码:
#include<bits/stdc++.h>
#define ll long long
#define MOD 998244353
#define INF 0x3f3f3f3f
#define mem(a,x) memset(a,x,sizeof(a))
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
int p[4005];
int d[4005];
int dp[4005];
int main()
{
int t,n;
cin>>t;
while(t--){
cin>>n;
for(int i=1;i<=2*n;i++){
scanf("%d",&p[i]);
}
vector<int>v;
int maxn=0;
for(int i=1;i<=2*n;i++){ //分离子串
if(maxn<p[i]){
maxn=p[i];
v.push_back(i);
}
}
v.push_back(2*n+1);
int sum=0;
for(int i=1;i<v.size();i++){
d[++sum]=v[i]-v[i-1];
}
//for(int i=1;i<=sum;i++)cout<<d[i]<<endl;
mem(dp,0);
for(int i=1;i<=sum;i++){ //dp部分
for(int j=n;j>=d[i];j--){
dp[j]=max(dp[j],dp[j-d[i]]+d[i]);
}
}
//for(int i=1;i<=n;i++)cout<<dp[i]<<endl;
if(dp[n]==n){
cout<<"YES"<<endl;
}else{
cout<<"NO"<<endl;
}
}
return 0;
}