Codeforces Round #658 (Div. 2) D. Unmerge
阿新 • • 發佈:2020-08-02
題目連結: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(falseView Code); 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 intcnt=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 }