題目鏈接: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;
}