Unmerge( 找规律 + 01背包 )
题意
给出一个序列,把这个序列拆成俩个序列,这俩个序列每次取最前面的最小值,构成一个新序列,这个新序列是不是原来的序列。
思路
每个取俩个序列front的最小值。
3 2 6 1 5 7 8 4,那么3 2 必定在一个序列、并且相邻
- 若不在一个序列,那先输出2 然后 3
- 若不相邻,那输出3之后,就不会输出2
基于以上规律,拆分成若干小的序列。
我们从这些小序列中选择出几个,看能不能构成俩个子序列中的一个。
可以的话,输出yes
这个过程就是01背包
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
int a[200010],b[200010];
int dp[2010];
vector<int>ans;
int main()
{
int t;
cin>>t;
while(t--)
{
ans.clear();
memset(dp,0,sizeof dp);
int n;
cin>>n;
for(int i=0;i<n*2;i++)
cin>>a[i];
a[n*2]=0x3f3f3f3f;
for(int i=0;i<n*2;i++)
{
int j=i;
while(j<=2*n && a[j+1]<a[i]) j++;
ans.push_back(j-i+1);
i=j;
}
// for(auto x:ans)
// cout<<x<<' ';
// cout<<endl;
dp[0]=1;
for(auto x : ans)
for(int j=2*n;j>=x;j--)
dp[j]=dp[j] | dp[j-x];
if(dp[n])
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}