xzq4121

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

洛谷P8769题解

update

2025.2.19

偶然间看到了自己以前的这篇题解,不能再让大家吃屎了, 所以修改了解析和代码,并增加了内容。

solution

方法

使用贪心。

很容易想到的一种贪心思路是从第一天开始枚举到最后一天,每一天吃一块当前可使用的所有巧克力中最便宜的一块,但如果我们仔细思考会发现酱紫贪心会有一个问题:

在前几天可能会把保质期长且便宜的巧克力吃完而浪费掉保质期短但较便宜的巧克力,然后导致最后几天只能吃保质期长但的巧克力甚至没有巧克力吃。

然后再注意到一个点:

由于有保质期的限制,若不考虑小蓝吃巧克力的话,我们可以发现每一天可使用的巧克力的数量是单调递减的,且后一天有的巧克力前一天必定会有。

因此若我们从后往前枚举,就会有两种情况:

  1. 这一天的最优巧克力被后几天吃完了,那么吃次优巧克力。
  2. 这一天的最优巧克力还有,那么吃最优巧克力。

这样就可以保证每一天做的都是最优决策。

例子:

输入
12 5
1 13 6
2 5 3
3 6 4
10 100 100
100 100 100
输出
21

在这里,如果从前往后,第二种和第三种会被跳过,所以输出为 66

实现

接下来考虑如何实现。

首先按保质期从大到小排序,然后开一个小根堆,里面存储巧克力的价格和数量,并以价格为第一关键字。

然后从后往前枚举每一天,把这一天新加入的可使用的巧克力入堆,接着将答案加上堆顶的巧克力的价值,并把堆顶的巧克力的数量减一,若此时数量为 0,则弹出堆顶。

复杂度分析

空间复杂度

开了一个大小为 N 的结构体,里面存储了 3 个信息,还有零散的几个变量,因此空间复杂度为 O(N)

时间复杂度

读入复杂度是 O(N),排序是 O(NlogN),贪心中由于每一种巧克力只会入堆一次,所以也是 O(NlogN)

则总时间复杂度为 O(NlogN)

code:

#include <bits/stdc++.h>
#define mp make_pair
using namespace std;
const int N=1e5+5;
int n,m,cnt=1,ans;
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;
struct node
{
	int v,t,s;
}a[N];
bool cmp(node x,node y)
{
	return x.t>y.t;
}
void input()
{
	scanf("%d %d",&n,&m);
	for(int i=1;i<=m;++i)
		scanf("%d %d %d",&a[i].v,&a[i].t,&a[i].s);	
	sort(a+1,a+m+1,cmp);
} 
void work()
{
	for(int i=n;i;--i)
	{
		while(a[cnt].t>=i)
		{
			q.push(mp(a[cnt].v,a[cnt].s));
			++cnt;
		}
		pair<int,int> x=q.top();
		q.pop();
		ans+=x.first;
		--x.second;
		if(x.second)
			q.push(x);
	}
	printf("%d",ans);
}
int main()
{
	input();
	work();
	return 0;
}

posted on   xzq4121  阅读(7)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示