一、题目
二、解法
复杂度允许枚举一类物品选取的个数,我们先枚举花费为 的物品个数。
剩余物品能选的最大价值是关于花费为 的选取物品个数 呈单峰函数的,因为选少了可能更优,会增大,然后当选的比不选的更差时,就会下降,所以我们可以用三分解决这个问题。但是可能会有平台(函数值相等),但是平台只会出现在下降趋势,出现平台就往小的那边分治就可以了。
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int M = 200005;
#define int long long
int read()
{
int x=0,f=1;char c;
while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
return x*f;
}
int n,m,ans,res,v,s1[M],s2[M];
vector<int> a[4];
bool cmp(int x,int y)
{
return x>y;
}
int cal(int x)
{
if(2*x>v) return 0;
int t=s2[x]+s1[min(v-2*x,(int)a[1].size())];
res=max(res,t);
return t;
}
void dich(int l,int r)
{
if(l>r) return ;
int m1=l+(r-l)/3,m2=r-(r-l)/3;
int t1=cal(m1),t2=cal(m2);
if(t1>=t2) dich(l,m2-1);
else dich(m1+1,r);
}
signed main()
{
n=read();m=read();
for(int i=1;i<=n;i++)
{
int w=read();
a[w].push_back(read());
}
for(int i=1;i<=3;i++)
sort(a[i].begin(),a[i].end(),cmp);
for(int i=0;i<a[1].size();i++)
s1[i+1]=s1[i]+a[1][i];
for(int i=0;i<a[2].size();i++)
s2[i+1]=s2[i]+a[2][i];
res=0;v=m;
dich(0,a[2].size());
ans=res;
for(int i=0,p=0;i<a[3].size();i++)
{
res=0;v=m-(i+1)*3;
if(v<0) break;
dich(0,a[2].size());
p+=a[3][i];
ans=max(ans,res+p);
}
printf("%lld\n",ans);
}