题目链接: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;
}