没证出来/fad
从大到小扫描每个数,对于三个集合(有序)依次考虑:如果当前集合能够放下,即放下之后不会爆空间也不会爆总和(加上最小的几个来填满剩下的),就直接放进去。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+3;
ll n,b[3],c[3],a[N],sa[N];
void Solve()
{
cin>>n;ll sum=0;vector<int>ans[3];
for(int i:{0,1,2})cin>>b[i],c[i]=0;
for(int i=1;i<=n;i++)cin>>a[i],sum+=a[i];
sort(a+1,a+n+1);
for(int i=1;i<=n;i++)sa[i]=sa[i-1]+a[i];
for(int i=n;i>=1;i--)
{
int fl=0;
for(int j=0;j<=2&&!fl;j++)if(b[j]&&c[j]+sa[b[j]-1]+a[i]<=(sum-1)/2)
b[j]--,c[j]+=a[i],ans[j].push_back(a[i]),fl=1;
if(!fl){cout<<"NO"<<endl;return;}
}
cout<<"YES"<<endl;
for(int i:{0,1,2})
{
for(int v:ans[i])cout<<v<<" ";
cout<<endl;
}
}
int main()
{
int T;cin>>T;
while(T--)Solve();
return 0;
}
代码和思路来自 @hanghang