Codeforces Round #658 (Div. 1)B. Unmerge(DP)

观察后思考得出:对于一个数 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;
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_43353639/article/details/107540483