[CF808E]Selling Souvenirs

89 篇文章 0 订阅

题目

传送门 to luogu

思路

注意到重量只有 1 , 2 , 3 1,2,3 1,2,3 三种取值,这肯定可以作为突破口。

如果只有重量 1 , 2 1,2 1,2 就很好计算,可以贪心。重量为偶数,肯定是两个重量为 1 1 1 、一个重量为 2 2 2 作为基础单位。重量为奇数,一开始拿一个重量为 1 1 1 的,问题转化为上面的情形。

然后枚举重量为 3 3 3 的有多少个即可。复杂度 O ( n log ⁡ n ) \mathcal O(n\log n) O(nlogn) ,瓶颈是排序(贪心过程)。

代码

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
inline int readint(){
	int a; scanf("%d",&a); return a;
}

template < typename T >
void getMax(T&a,T b){ if(a < b) a = b; }

const int MaxN = 100005;
int a[4][MaxN];
long long dp[MaxN*3], s[MaxN*3];

int main(){
	int n = readint(), m = readint();
	for(int i=1; i<=n; ++i){
		int w = readint();
		a[w][++ a[w][0]] = readint();
	}
	for(int i=1; i<4; ++i)
		sort(a[i]+1,a[i]+a[i][0]+1,greater<int>());
	for(int i=1; i<=a[3][0]; ++i)
		s[i*3] = s[i*3-3]+a[3][i];
	int p[3] = {0,1,1}; dp[0] = 0;
	for(int i=2; i<=m; i+=2){
		int one = 0, two = 0;
		if(p[1]+1 <= a[1][0])
			one = a[1][p[1]]+a[1][p[1]+1];
		if(p[2] <= a[2][0])
			two = a[2][p[2]];
		if(one >= two)
			p[1] += 2, dp[i] = dp[i-2]+one;
		else p[2] ++, dp[i] = dp[i-2]+two;
	}
	p[1] = 2, p[2] = 1; dp[1] = a[1][1];
	for(int i=3; i<=m; i+=2){
		int one = 0, two = 0;
		if(p[1]+1 <= a[1][0])
			one = a[1][p[1]]+a[1][p[1]+1];
		if(p[2] <= a[2][0])
			two = a[2][p[2]];
		if(one >= two)
			p[1] += 2, dp[i] = dp[i-2]+one;
		else p[2] ++, dp[i] = dp[i-2]+two;
	}
	for(int i=1; i<=m; ++i){
		getMax(dp[i],dp[i-1]);
		getMax(s[i],s[i-1]);
	}
	long long ans = 0;
	for(int i=0; i<=m; ++i)
		getMax(ans,s[i]+dp[m-i]);
	printf("%lld\n",ans);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值