视频加载失败

安吉D8-C

1200 字
6 分钟
安吉D8-C
原题呈现

P12247 跳舞机#

题目描述#

小 O 想要经营电 van 城,跳舞机的运营非常重要.

小 O 的电 van 城有一台跳舞机,跳舞机在同一时间至多有一名玩家游玩,每局游戏需要完整且连续地游玩 kk 分钟.

电 van 城将营业 mm 分钟.期间有 nn 名玩家想要游玩跳舞机,编号 1n1\sim n.编号为 ii 的玩家会在营业的第 lil_i 分钟到第 rir_i 分钟(包括 lil_irir_i)待在电 van 城,在此期间可以游玩任意局跳舞机.并且,每游玩一局,会产生 wiw_i 的兴奋值.注意,如果玩家 ii 要玩一局跳舞机,则每局游戏的 kk 分钟必须完全包含于玩家的停留时间 [li,ri][l_i,r_i]

小 O 想要最大化所有玩家的兴奋值之和,请你帮他求出最大的兴奋值之和.

输入格式#

输入共 n+1n+1 行.

第一行输入三个整数 n,m,kn,m,k,分别表示玩家个数、营业时间、游玩一局跳舞机需要的时间.

2n+12\sim n+1 行,第 i+1i+1 行有三个整数 li,ri,wil_i,r_i,w_i,表示编号为 ii 的玩家的停留时间和游玩一局产生的兴奋值.

输出格式#

输出共一行一个整数,表示最大的兴奋值之和.

输入输出样例 #1#

输入 #1#

3 6 2
1 5 1
5 6 2
5 6 3

输出 #1#

5

输入输出样例 #2#

输入 #2#

4 7 3
1 7 1
2 5 4
4 7 5
1 2 10

输出 #2#

9

说明/提示#

样例 #1 解释#

可以让编号为 11 的玩家在第 121\sim2 分钟、第 343\sim 4 分钟玩一局跳舞机,编号为 33 的玩家在第 565\sim 6 分钟玩一局.兴奋值的总和为 1+1+3=51+1+3=5,可以发现没有让兴奋值总和更大的方案.

样例 #2 解释#

可以让编号为 22 的玩家在第 242\sim4 分钟玩一局跳舞机,编号为 33 的玩家在第 575\sim 7 分钟玩一局.兴奋值的总和为 4+5=94+5=9,可以发现没有让兴奋值总和更大的方案.

数据范围#

对于所有数据,满足:

  • 1n,m,k5×1051\le n,m,k\le 5\times 10^5
  • kmk\le m
  • 1lirim1\le l_i\le r_i\le m
  • 1wi1091\le w_i\le 10^9

Li=rili+1L_i=r_i-l_i+1,则具体测试点限制如下:

测试点编号nn 的范围mm 的范围特殊性质
131\sim 3n5n\le 5m10m\le 10wi20w_i\le 20
464\sim 6n105n\le 10^5m105m\le 10^5Li=k=1L_i=k=1
7107\sim10n1000n\le 1000m1000m\le 1000
111311\sim 13n105n\le 10^5m105m\le 10^5Li=kL_i=k
141614\sim 16n100n\le 100m105m\le 10^5
172017\sim 20n105n\le 10^5m105m\le 10^5wi=1w_i=1
21,2221,22n105n\le 10^5m105m\le 10^5
232523\sim 25n5×105n\le 5\times 10^5m5×105m\le 5\times 10^5

此题使用 dp.

定义状态 dp[i] 表示到第 ii 分钟结束时的最大收益.(这样定义状态的方法叫做依照问题法.在实践中,我们可以依照题目所求的内容来制定状态)

不难发现初始状态:

dp[0] = 0;

由于此题推进时间或赢得分数的途径只有:

  • 让一个人玩跳舞机
  • 让跳舞机闲置

,因此不难发现转移方程:

dpi=max{maxjljik<irj(dpik+wj),dpi1}dp_i = \max\{\max_{j}^{l_j\leq i-k < i \leq r_j} (dp_{i-k} + w_j),dp_{i-1}\}

这个转移方程是 O(n2)O(n^2) 的,如何优化?

将转移方程变形为:

dpi=max{dpik+maxjljik<irjwj,dpi1}dp_i = \max\{dp_{i-k} + \max_{j}^{l_j\leq i-k < i \leq r_j} w_j,dp_{i-1}\}

加下来,只需要算出:

d=maxjljik<irjwjd=\max_{j}^{l_j\leq i-k < i \leq r_j} w_j

即可.

由于 ii 在枚举时是递增的,所以可以使用优先队列优化.使用一个优先队列,其中储存所有可能在当前时刻恰好结束一局跳舞机的玩家(即呆在电玩城中的时间大于等于 kk).

将所有的玩家按照来的顺序排序.每当遍历到时刻 ii 时,将所有第 ik+1i-k+1 这个时刻进入电玩城的玩家加入优先队列,这些玩家有可能在第 ii 秒结束时正好结束一局跳舞机(从第 ik+1i-k+1 到第 ii 秒).

然后,在优先队列中获取 ww 最高的一名玩家,如果该玩家已经离开电玩城了(即 ri<ir_i < i),那么将该玩家从优先队列中删去,重新选取一名 ww 最高的玩家.让该玩家在 ik+1i-k+1ii 这一段时间里游玩跳舞机.这名玩家的 ww 就是上面需要算出的 dd

标程

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5e5 + 100;
struct People {
int l, r, w;
friend bool operator<(const People a, const People b) { return a.w < b.w; }
} a[N];
priority_queue<People> pq;
int n, m, k;
ll f[N];
signed main() {
cin >> n >> m >> k;
for (int i = 1; i <= n; i++) {
cin >> a[i].l >> a[i].r >> a[i].w;
}
sort(a + 1, a + n + 1,
[](const People a, const People b) { return a.l < b.l; });
int ptr = 0;
for (int i = 1; i <= m; i++) {
while (ptr != n && a[ptr + 1].l <= i - k + 1) {
pq.push(a[++ptr]);
}
f[i] = f[i - 1];
while (!pq.empty()) {
People top = pq.top();
if (top.r < i) {
pq.pop();
continue;
}
f[i] = max(f[i], f[i - k] + top.w);
break;
}
}
cout << f[m];
return 0;
}

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

安吉D8-C
https://blog.jerrylab.top/posts/problem/anji2026/D8/C/
作者
Jerry
发布于
2026-08-09
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
Jerry
Hello, I'm Jerry.
公告
欢迎来到我的博客!这是一则示例公告。
分类
标签
最新动态
站点统计
文章
80
分类
3
标签
35
总字数
89,198
运行时长
0
最后活动
0 天前
站点信息
构建平台
Cloudflare Pages
博客版本
Firefly v6.16.5
文章许可
CC BY-NC-SA 4.0