【Codeforces】#658 D.Unmerge DP
阿新 • • 發佈:2020-08-17
D.Unmerge
題意
定義 \(merge(a,b)\) :
a,b是兩個長度均為 n 的陣列.
如果 \(a_1 < b_1\) \(merge(a,b)\) = \(a_1\) + \(merge(a_2+ a_3 + a_4 ... , b)\)
如果 \(a_1 > b_1\) \(merge(a,b)\) = \(b_1\) + \(merge( a , b_2+b_3+b_4+...)\)
給出一個正整數 n ,以及長度為 2 * n 的全排列,問這個全排列是否可能是兩個長度為 n 的陣列merge 得到
思路
寫一下就會發現:
如果第 i 個數字是 x ,第一個下標大於 i ,並且 \(p_j > x\)
這 j - i 個數字應該來自一個數組。
那麼我們統計應該來自一個數組的數字個數,進行 DP ,判斷能否形成長度為 n 的陣列即可。
程式碼
/* * @Autor: valk * @Date: 2020-07-17 16:50:40 * @LastEditTime: 2020-08-17 11:34:55 * @Description: 如果邪惡 是 華麗殘酷的樂章 它的終場 我會親手寫上 晨曦的光 風乾最後一行憂傷 黑色的墨 染上安詳 */ #include <bits/stdc++.h> #define fuck system("pause") #define emplace_back push_back #define pb push_back using namespace std; typedef long long ll; typedef unsigned long long ull; const int mod = 1e9 + 7; const int seed = 12289; const double eps = 1e-6; const int inf = 0x3f3f3f3f; const int N = 2e5 + 10; int arr[N], brr[N], dp[N]; int main() { int _; scanf("%d", &_); while (_--) { int n, cnt = 0; scanf("%d", &n); n *= 2; for (int i = 1; i <= n; i++) { scanf("%d", &arr[i]); } for (int i = 1; i <= n;) { int j = i; while (j <= n && arr[j] <= arr[i]) j++; brr[++cnt] = j - i; i = j; } memset(dp, 0x8f, sizeof(dp)); dp[0] = 1; for (int i = 1; i <= cnt; i++) { for (int j = 2000; j >= brr[i]; j--) { dp[j] = max(dp[j], dp[j - brr[i]]); } } if (dp[n / 2] == 1) { printf("YES\n"); } else { printf("NO\n"); } } // fuck; return 0; }