观察后思考得出:对于一个数 a i a_i ai,它后面那些连续的小于 a i a_i ai得 a j a_j aj ( j > i ) (j>i) (j>i),一定是和 a i a_i ai在同一个集合中。
因此找到 L I S LIS LIS最长上升自序列,根据子序列中每个元素划分成若干个小部分,就变成了01背包问题。
#include<bits/stdc++.h>
using namespace std;
#define MAXN 4105
#define ll long long
int n;
int a[MAXN];
int check[MAXN];
int main()
{
int t;
cin>>t;
while(t--) {
scanf("%d", &n);
for (int i = 1; i <= 2 * n; i++)
scanf("%d", a + i);
int pre=0;
vector<int>v;
for (int i = 1; i <= 2 * n; i++) {
if (a[i] > a[pre]) {
if(pre!=0)
v.push_back(i-pre);
pre = i;
}
}
memset(check,0, sizeof(check));
check[0]=1;
for(int i=0;i<v.size();i++)
{
for(int j=2*n-1;j>=0;j--)
if(j+v[i]<=2*n)
check[j+v[i]]|=check[j];
}
if(check[n])
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
}