P2672 [NOIP 2015 普及组] 推销员 解题笔记

题目链接

题意

阿明要给胡同里的 \(n\) 个住户推销,第 \(i\) 个住户距离为 \(s_i\),推销完会产生 \(a_i\) 的疲劳值,每走一个距离会产生 \(1\) 点疲劳值。推销完后需原路返回,分别求不走无用路时推销 \(x\) 个住户的最大疲劳值(\(x\)\(1\)\(n\) 的任意值)。

思路

考虑贪心。

如果没有距离,那么就是贪疲劳值,直接取前 \(x\) 个疲劳值最大的就好了。

加上距离后有两种情况:

  • 直接取前 \(x\) 个疲劳值最大的。
  • 舍弃疲劳值最小的,选择距离最远的。

代码实现:

  • 先将住户按 \(a_i\) 降序排序。

  • 计算 \(sum\) 数组为 \(a_i\) 的前缀和。\(s\)\(s_i\) 的最大值。\(maxx\)\(a_i + 2 \times s_i\) 的后缀和。

  • 循环 \(1\)\(n\) 计算答案。

代码

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int n, sum[N], s[N], maxx[N], mx;
struct node
{
	int a, s;
}a[N];
bool cmp(node a, node b)
{
	return a.a > b.a;
}
signed main()
{
	cin >> n;
	for(int i = 1; i <= n; i ++) cin >> a[i].s;
	for(int i = 1; i <= n; i ++) cin >> a[i].a;
	sort(a + 1, a + n + 1, cmp);
	for(int i = 1; i <= n; i ++)
	{
		sum[i] = sum[i - 1] + a[i].a;
		s[i] = max(s[i - 1], a[i].s);
	}
	for(int i = n; i >= 1; i --)
	{
		maxx[i] = max(maxx[i + 1], a[i].a + 2 * a[i].s);
	}
	for(int i = 1; i <= n; i ++)
	{
		mx = max(mx, a[i].s);
		int ans = max(sum[i] + mx * 2, sum[i - 1] + maxx[i]);
		cout << ans << endl;
	}
}
posted @ 2026-06-30 15:18  Luowj  阅读(2)  评论(0)    收藏  举报