CF1906E Merge Not Sort
考虑怎样的一段数一定要被绑在一块(即一定要在同一个序列并且相邻),我们可以通过如下的方式来寻找这样的一段:
扫一遍输入序列
这样做显然是正确的。因为如果一个块的任意一个非块头元素放到另一个序列都会被先放到
然后把所有块打包起来,看能不能把块往 std::set 构造方案。
最后记得对于最终序列中的每一个块按照块头元素大小升序排序。
放代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(false);
int n,l=0; cin>>n;
vector<int> c(n<<1);
for(auto &i:c)cin>>i;
vector<int> h=c,s(n<<1);
for(int i=1;i<n<<1;i++)
if(h[i]<h[i-1])h[i]=h[i-1],s[i-1]=1;
// 标记一下位置
vector<vector<int> > w,a,b;
while(l<n<<1){
vector<int> v;
while(l<n<<1&&s[l])
v.emplace_back(c[l++]);
v.emplace_back(c[l++]);
w.emplace_back(v);
} // 把所有块找出来
vector<set<int> > f(n+1);
for(int j=0;j<w.size();j++)
for(int i=n-1;~i;i--)
if(!i||!f[i].empty()){
if(i+w[j].size()<=n&&f[i+w[j].size()].empty()){
for(int k:f[i])f[i+w[j].size()].emplace(k);
f[i+w[j].size()].emplace(j);
}
} // 背包 DP,构造
if(f[n].empty()){cout<<"-1\n"; return 0;}
for(int i=0;i<w.size();i++)
if(f[n].find(i)==f[n].end())b.emplace_back(w[i]);
else a.emplace_back(w[i]); // 分配到 2 个序列
sort(a.begin(),a.end()); // 对块进行排序
sort(b.begin(),b.end());
for(auto i:a)for(int j:i)cout<<j<<' ';
cout<<endl; // 直接遍历输出
for(auto i:b)for(int j:i)cout<<j<<' ';
cout<<endl;
return 0;
}