CF#658 Div2 D题 Unmerge(dp)

题目

链接

思路

尽可能将题目给出的串进行拆分,拆得各段尽可能小,然后dp看是否能拿取某些段构成长度为n的串,若可以,则YES。

拆分的原则为,拆出来的各段的开头必定大于段中的各个数字。遇到大于段头的数字,则新开一段。

代码

#include
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 10;
const int INF = 0x3f3f3f3f;
vector <int> ans;
int n, a[maxn], len[maxn], dp[maxn];
void pre_work(){
    scanf("%d", &n);
    ans.clear();
    int maxi = -1;
    for(int i = 1; i <= 2 * n; i++){
        scanf("%d", &a[i]);
        if(maxi <= a[i]){
            maxi = a[i];
            ans.push_back(i);
        }
    }
    ans.push_back(2 * n + 1);
}
void main_work(){
    int cnt = ans.size() - 1;//len的个数
    for(int i = 1; i < ans.size(); i++)
        len[i] = ans[i] - ans[i - 1];
    for(int i = 0; i <= n; i++)
        dp[i] = -INF;
    dp[0] = 0;
    for(int i = 1; i <= cnt; i++){
        for(int j = n; j >= len[i]; j--){
            dp[j] = max(dp[j], dp[j - len[i]] + len[i]);
        }
    }
    printf("%s\n", dp[n] == n ? "YES" : "NO");
}
int main(){
    int t; scanf("%d", &t);
    while(t--){
        pre_work();
        main_work();
    }
}

你可能感兴趣的:(CF#658 Div2 D题 Unmerge(dp))