Codeforces Round #658 (Div. 2) D. Unmerge ###K ###K //K
题目链接:https://codeforces.ml/contest/1382/problem/D
题意:给一段长为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 }

浙公网安备 33010602011771号