题解
将(a_i,b_i)4种情况的书分别存入4个优先队列。首先考虑满足(k),也就是在两人喜欢的书数目(le k)、所选书目(le m)的条件下优先选择(a_i=b_i=1)的书,其次是将(a_i=0,b_i=1)和(a_i=1,b_i=0)的两本书绑在一起选择。如果这样选择后喜欢书目仍(<k),则判断无法满足。如果选择书目仍(le m),这时可以考虑由两本绑在一起的书替换一本(a_i=b_i=1)的书,或者新读一本当前时长最短的书,两者都可以使选择书目(+1)。每次从这两种方案中取最优,直到选够(m)本书即可。
AC代码
#include<bits/stdc++.h>
#define mp make_pair
#define pii pair<int,int>
using namespace std;
const int N=2e5+10,inf=0x3f3f3f3f;
int t[N],a[N],b[N],n1,n2;
priority_queue<pii ,vector<pii >,greater<pii> > q[5];
pii ans[5][N];
int main()
{
int n,m,k,res=0;
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&t[i],&a[i],&b[i]);
if(a[i] && b[i]) q[0].push(mp(t[i],i));
if(!a[i] && b[i]) q[1].push(mp(t[i],i));
if(a[i] && !b[i]) q[2].push(mp(t[i],i));
if(!a[i] && !b[i]) q[3].push(mp(t[i],i));
}
while(m && k && !q[0].empty())
{
res+=q[0].top().first;
ans[0][++n1]=q[0].top(); q[0].pop();
m--,k--;
}
while(m>1 && k && !q[1].empty() && !q[2].empty())
{
res+=q[1].top().first+q[2].top().first;
ans[1][++n2]=q[1].top(),ans[1][++n2]=q[2].top();
q[1].pop(),q[2].pop();
m-=2,k--;
}
if(k) {printf("-1"); return 0;}
while(m--)
{
int minn=inf;
for(int i=0;i<=3;i++)
if(!q[i].empty()) minn=min(minn,q[i].top().first);
if(n1 && !q[1].empty() && !q[2].empty())
{
if(q[1].top().first+q[2].top().first-ans[0][n1].first<minn)
{
ans[1][++n2]=q[1].top(),ans[1][++n2]=q[2].top();
res+=q[1].top().first+q[2].top().first-ans[0][n1].first;
q[1].pop(),q[2].pop();
q[0].push(ans[0][n1]); n1--;
continue;
}
}
for(int i=0;i<=3;i++)
{
if(!q[i].empty() && minn==q[i].top().first)
{
ans[1][++n2]=q[i].top(),q[i].pop();
res+=minn; break;
}
}
}
printf("%d
",res);
for(int i=1;i<=n1;i++) printf("%d ",ans[0][i].second);
for(int i=1;i<=n2;i++) printf("%d ",ans[1][i].second);
return 0;
}