补题,题目链接:Codeforces Round #658 (Div. 2) D. Unmerge
Let a and b be two arrays of lengths n and m, respectively, with no elements in common. We can define a new array merge(a,b) of length n+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
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 n distinct integers from 1 to n 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).
The first line contains a single integer t (1≤t≤1000) — the number of test cases. Next 2t lines contain descriptions of test cases.
The first line of each test case contains a single integer n (1≤n≤2000).
The second line of each test case contains 2n integers p1,…,p2n (1≤pi≤2n). It is guaranteed that p is a permutation.
It is guaranteed that the sum of n across all test cases does not exceed 2000.
For each test case, output “YES” if there exist arrays a, b, each of length n and with no common elements, so that p=merge(a,b). Otherwise, output “NO”.
merge(a,b)操作:两个数组中,把较小的元素依次拿出排序。
现有一个2*n的数组p,问你是否存在两个长度恰好为n的数组可以通过merge操作生成数组p。
可以理解成,满足merge操作的子串,是否能把长度不一样的子串拼装成两个大小为n的数组。
某一个数及它后面比它小的数,必定属于同个数组,可以预处理各个子串的长度,若出现长度大于n的片段肯定是NO,再通过01背包dp选择判断。
#pragma GCC optimize(2)
#include
using namespace std;
#define endl "\n"
const int MAX=1e4+7;
int a[MAX],dp[MAX];
int main(){
ios_base::sync_with_stdio(0);cin.tie(0);
int t;cin>>t;
while(t--)
{
int n;cin>>n;
int mx=0,x=0,l=1,cnt=0;
cin>>x;mx=x;
for(int i=1;i<2*n;i++){
cin>>x;
if(x<mx) l++;
else{
a[cnt++]=l;
mx=x;l=1;
}
}
a[cnt++]=l;
int f=0;
for(int i=0;i<cnt;i++){
if(a[i]>n){
f=1;break;
}
}
if(f){
cout<<"NO"<<endl;continue;
}
memset(dp,0,sizeof(dp));
dp[0]=1;
for(int i=0;i<cnt;i++)
for(int j=n;j>=a[i];j--)
dp[j]=dp[j]||dp[j-a[i]];
cout<<(dp[n]?"YES":"NO")<<endl;
}
return 0;
}