Codeforces-808E - Selling Souvenirs(分类讨论,双指针)

题目连接:Codeforces-808E - Selling Souvenirs

题意是一个背包问题,n和m都很大,但是物品重量在1和3之间

假设只有重量为2和3的两个物品,那么可以设置双指针来取,在O(n)的时间内可以解决。
那么我们分类讨论取重量为1物品的情况。如果我们取偶数个重量为1的物品,那么可以把重量为1的物品合成为重量为2的物品。
如果我们取奇数个重量为1的物品,那么先取出价值最大的那个物品,剩下的跟偶数情况一样处理就好了。

#include<bits/stdc++.h>
#define mp make_pair
#define pr pair<int,int>
#define fi first
#define se second
using namespace std;
typedef long long ll;
const int N=1e5+7;
vector<ll> v1,v2,v3;
ll ans=0,res=0;
int n,m,ccc;
void solve()
{
    int c=ccc;
    int l,r;
    for(l=(int)v2.size()-1;l>=0&&c+2<=m;l--) res+=v2[l],c+=2;
    ++l;
    r=(int)v3.size()-1;
    ans=max(ans,res);
    while((l<v2.size()||v2.size()==0)&&r>=0)
    {
        res+=v3[r];c+=3;
        while(c>m&&l<v2.size()) c-=2,res-=v2[l],++l;
        if(c>m) break;
        ans=max(ans,res);
        --r;
    }
}
int main()
{
    cin>>n>>m;
    int w;ll c;
    for(int i=0;i<n;i++)
    {
        cin>>w>>c;
        if(w==1) v1.push_back(c);
        else if(w==2) v2.push_back(c);
        else v3.push_back(c);
    }
    sort(v3.begin(),v3.end());
    vector<ll> t2=v2;
    sort(v1.begin(),v1.end());
    for(int i=(int)v1.size()-1;i-1>=0;i-=2)
        v2.push_back(v1[i]+v1[i-1]);
    sort(v2.begin(),v2.end());
    ccc=0;
    solve();
    v2=t2;
    if(v1.size()) res=v1[v1.size()-1],ccc=1;
    else res=0,ccc=0;
    for(int i=(int)v1.size()-2;i-1>=0;i-=2)
        v2.push_back(v1[i]+v1[i-1]);
    sort(v2.begin(),v2.end());
    solve();
    cout << ans << endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值