原题链接:Problem - 730I - Codeforces
题意:有 n个学生每人有两种技能,分别是 a,b 表示编程能力和运动能力。你需要将他们分为两个团队分别参加编程比赛和体育比赛,编程团队有 p 人,体育团队有 s 人,一个学生只能参加其中一项。每个团队的力量是其成员在对应领域能力总和,请问如何分配能使得两个团队的实力和最大?
思路:反悔贪心。可以想到肯定是需要让编程能力强的人去编程,运动能力强的人去运动,但是贪心无法保证正确性,例如一个人编程能力和运动能力分别是6 5,另一个人是6 1,那么应该让第一个人去运动,第二个人编程,如果直接贪心是错误的。那么就需要对之前的贪心进行反悔,首先先把编程能力最强的p人放到编程团队,对于运动团队的选人来说,有二种情况,情况一:直接在没选择的人中选择运动能力最强的,情况二:将编程团队中运动能力-编程能力最大的人放入运动团队,然后从没选的人里面取出最强的编程能力放入编程团队。二种情况取最大值就可以了。使用三个堆a,b,c来维护,b维护没选择的人里面运动能力最强的,a维护没选择里面编程能力最强的,c维护编程团队里面运动能力-编程能力最强的。
//冷静,冷静,冷静
//调不出来就重构
//#pragma GCC optimize(2)
//#pragma GCC optimize("O3")
#include<bits/stdc++.h>
#define count2(x) __builtin_popcountll(x)
#define is2(x) __builtin_ffsll(x)
#define endl '\n'
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<ll,ll> pii;
const int N=1e6+10,mod=1000000007;
struct node
{
ll id,num;
}p[N],q[N];
bool gz(node &a,node &b)
{
return a.num>b.num;
}
bool gz1(node &a,node &b)
{
return a.id<b.id;
}
ll ans[N];
struct gz2
{
bool operator()(const node &a,const node &b)const
{
return a.num<b.num;
}
};
void Jiuyuan()
{
ll n,x,y;cin>>n>>x>>y;
for(int i=1;i<=n;i++)
{
cin>>p[i].num;p[i].id=i;
}
for(int i=1;i<=n;i++)
{
cin>>q[i].num;q[i].id=i;
}
sort(p+1,p+1+n,gz);
ll max1=0;
for(int i=1;i<=x;i++)
{
ans[p[i].id]=1;
max1+=p[i].num;
}
sort(p+1,p+1+n,gz1);
priority_queue<node,vector<node>,gz2> a,b,c;
for(int i=1;i<=n;i++)
{
a.push({i,p[i].num});
b.push({i,q[i].num});
c.push({i,q[i].num-p[i].num});
}
for(int i=1;i<=y;i++)
{
ll now=-1e18,id1,id2,hh=0;
while(b.size()&&ans[b.top().id])b.pop();
if(b.size()&&b.top().num>now)
{
now=b.top().num;
hh=1;
id2=b.top().id;
}
while(a.size()&&ans[a.top().id])a.pop();
while(c.size()&&ans[c.top().id]!=1)c.pop();
if(a.size()&&c.size())
{
ll v=a.top().num+c.top().num;
if(v>now)
{
hh=2;
id2=c.top().id;
id1=a.top().id;
now=v;
}
}
max1+=now;
if(hh==1)
{
ans[id2]=2;
b.pop();
}
else
{
ans[id2]=2;ans[id1]=1;
a.pop();c.pop();
c.push({id1,q[id1].num-p[id1].num});
}
}
cout<<max1<<endl;
for(int i=1;i<=n;i++)if(ans[i]==1)cout<<i<<' ';
cout<<endl;
for(int i=1;i<=n;i++)if(ans[i]==2)cout<<i<<' ';
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
ll T=1;
// cin>>T;
while(T--)
{
Jiuyuan();
}
return 0;
}