1. 程式人生 > 實用技巧 >Codeforces Round #658 (Div. 2) D. Unmerge

Codeforces Round #658 (Div. 2) D. Unmerge

題目連結:https://codeforc.es/contest/1382/my

題意:給一段長為2n 的排列方式(permutation) 問 能否找到對應的 兩段n 組成的 序列 構成這段排列方式

當a[1]<b[1]時候 將a[1] 取出,然後變成(a[2]……a[n] 和b[1] ……b[n])重複操作 反之則取b[1] 取出的順序即為得到的序列的順序

思路:手動模擬一下 就可以發現 後面的小的數必須跟在前面的大的數後面, 這是相對固定的順序 如 3 2 6 1 5 7 8 4

3 2 為一組 6 1 5 為一組 7 為一組 8 4為一組 分成了四組 那麼我們只需要看這些組能不能拼成一個n的序列就知道是否滿足了

那麼把長度當作重量也當作價值,跑一遍01揹包 看dp[n]是否為n 即可

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define ull unsigned long long
 5 #define pb push_back
 6 const int maxn=1e5+10;
 7 const int mod=1e9+7;
 8 int p[5005];
 9 int dp[2005];
10 
11 int main()
12 {
13     ios::sync_with_stdio(false
); 14 cin.tie(0); 15 int t; 16 cin>>t; 17 while(t--) 18 { 19 int n; 20 cin>>n; 21 memset(dp,0,sizeof(dp)); 22 vector<int>a; 23 for(int i=1;i<=n*2;i++) 24 { 25 cin>>p[i]; 26 } 27 int
cnt=p[1]; 28 int sum=1; 29 for(int i=2;i<=n*2;i++) 30 { 31 if(p[i]<cnt) 32 { 33 sum++; 34 } 35 else 36 { 37 if(sum) 38 a.pb(sum); 39 sum=1; 40 cnt=p[i]; 41 } 42 } 43 if(sum) 44 a.pb(sum); 45 int len=a.size(); 46 for(int i=0;i<len;i++) 47 { 48 for(int j=n;j>=0;j--) 49 { 50 if(j>=a[i]) 51 { 52 dp[j]=max(dp[j],dp[j-a[i]]+a[i]); 53 } 54 } 55 } 56 if(dp[n]==n) 57 { 58 cout<<"YES"<<'\n'; 59 } 60 else 61 cout<<"NO"<<'\n'; 62 63 } 64 65 66 67 }
View Code