Codeforces - Reading Books (hard version)

題目鏈接:Codeforces - Reading Books (hard version)


我們可以發現如果我們選擇(1,1)的物品確定之後,那麼其他物品的選擇則變成了必然的。

然後可以枚舉選擇幾個(1,1)的物品,那麼複雜度太高了,需要用數據結構維護選的物品。

其實還有一個方法,我們可以發現選擇(1,1)類型的物品是具有三分性的,必然存在某個中間點是最優的。

所以直接三分之後暴力找即可。


AC代碼:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=2e5+10;
int n,m,k,res=2e9+1,num;
vector<pair<int,int> > v[4];
vector<int> ans;
inline int check(int mid){
	if((int)v[1].size()<k-mid)	return 2e9+1;
	if((int)v[2].size()<k-mid)	return 2e9+1;
	if(mid+max(0,k-mid)*2>m)	return 2e9+1;
	int nd=m-mid,res=0; vector<pair<int,int> > vec; ans.clear();
	for(int i=0;i<mid;i++)	res+=v[3][i].first,ans.push_back(v[3][i].second);
	for(int i=mid;i<v[3].size();i++)	vec.push_back(v[3][i]);
	for(int i=0;i<k-mid;i++)	
		res+=v[1][i].first+v[2][i].first,nd-=2,
		ans.push_back(v[1][i].second),ans.push_back(v[2][i].second);
	for(int i=max(0,k-mid);i<v[1].size();i++)	vec.push_back(v[1][i]);
	for(int i=max(0,k-mid);i<v[2].size();i++)	vec.push_back(v[2][i]);
	for(int i=0;i<v[0].size();i++)	vec.push_back(v[0][i]);
	sort(vec.begin(),vec.end());
	for(int i=0;i<nd&&i<vec.size();i++)	res+=vec[i].first,ans.push_back(vec[i].second);
	return res;
}
signed main(){
	cin>>n>>m>>k;
	for(int i=1,t,a,b;i<=n;i++)	
		scanf("%d %d %d",&t,&a,&b),v[a*2+b].push_back({t,i});
	for(int i=0;i<4;i++)	sort(v[i].begin(),v[i].end());
	int l=0,r=min(m,(int)v[3].size());
	while(r-l>10){
		int midl=l+(r-l)/3,midr=r-(r-l)/3;
		if(check(midl)>=check(midr))	l=midl;
		else	r=midr;
	}
	for(int i=l;i<=r;i++){
		int tmp=check(i);
		if(tmp<res)	res=tmp,num=i;
	}
	if(res==2e9+1)	return puts("-1"),0;
	cout<<res<<endl; check(num);
	for(int i:ans) printf("%d ",i);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章