CF1374E2 Solution

题目链接

题解

\(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\n",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;
}
posted @ 2021-08-12 11:14  violet_holmes  阅读(36)  评论(0编辑  收藏  举报