题目相关
题目链接
AtCoder Beginner Contest 183 D 题,https://atcoder.jp/contests/abc183/tasks/abc183_d。
Problem Statement
We have a water heater, which supplies W liters of hot water per minute.
There are N people. The i-th person plans to use Pi liters of hot water per minute boiled by the heater from Time Si to Ti (excluding at Time Ti exactly). As hot water gets cold fast, it cannot be stored.
Is it possible to supply hot water to the people according to their plans?
Input
Input is given from Standard Input in the following format:
N W
S1 T1 P1
.
.
.
Sn Tn Pn
Output
If it is possible to supply hot water to the people according to their plans, print Yes
; otherwise, print No
.
Samples1
Sample Input 1
4 10
1 3 5
2 4 4
3 10 6
2 4 1
Sample Output 1
No
Explaination
Between Time 3 and 4, the 2-nd, 3-rd, and 4-th persons plan to use 4, 6, and 1 liter(s) of hot water per minute, for a total of 11 liters per minute.
The water heater can only supply 10 liters of hot water per minute, which is not enough.
Samples2
Sample Input 2
4 10
1 3 5
2 4 4
3 10 6
2 3 1
Sample Output 2
Yes
Samples3
Sample Input 3
6 1000000000
0 200000 999999999
2 20 1
20 200 1
200 2000 1
2000 20000 1
20000 200000 1
Sample Output 3
Yes
Constraints
- 1≤N≤2×10^5
- 0≤Si<Ti≤2×10^5
- 1≤W,Pi≤10^9
- All values in input are integers.
题解报告
题目翻译
一个热水器,每分钟可以提供 W 升热水,现在有 N 个人使用,第 i 个人计划每分钟使用 Pi 升热水,从 Si 时间开始到 Ti 结束(不包括 Ti 时间点)。问给出的使用计划是否可行。
样例数据分析
样例数据 1
根据样例数据可知,热水器可以每分钟提供 10 升水。
第一个人数据,从第 1 分钟开始到第 3 分钟结束,每分钟使用 5 升。因此可以写出数据表格如下:
时间 | 用水 |
1 | 5 |
2 | 5 |
第二个人数据,从第 2 分钟开始到第 4 分钟结束,每分钟使用 4 升。因此可以写出数据表格如下:
时间 | 用水 |
1 | 5 |
2 | 5+4=9 |
3 | 4 |
第三个人数据,从第 3 分钟开始到第 10 分钟结束,每分钟使用 6 升。因此可以写出数据表格如下:
时间 | 用水 |
1 | 5 |
2 | 5+4=9 |
3 | 4+6=10 |
4 | 6 |
5 | 6 |
6 | 6 |
7 | 6 |
8 | 6 |
9 | 6 |
第四个人数据,从第 2 分钟开始到第 4 分钟结束,每分钟使用 1 升。因此可以写出数据表格如下:
时间 | 用水 |
1 | 5 |
2 | 5+4+1=10 |
3 | 4+6+1=11 |
4 | 6 |
5 | 6 |
6 | 6 |
7 | 6 |
8 | 6 |
9 | 6 |
从表格数据可以看出,在第 3 分钟,需要的热水为 11 升,超过了热水器可以供应的用水。所以输出 No。
样例数据 2
根据样例数据可知,热水器可以每分钟提供 10 升水。
第一个人数据,从第 1 分钟开始到第 3 分钟结束,每分钟使用 5 升。因此可以写出数据表格如下:
时间 | 用水 |
1 | 5 |
2 | 5 |
第二个人数据,从第 2 分钟开始到第 4 分钟结束,每分钟使用 4 升。因此可以写出数据表格如下:
时间 | 用水 |
1 | 5 |
2 | 5+4=9 |
3 | 4 |
第三个人数据,从第 3 分钟开始到第 10 分钟结束,每分钟使用 6 升。因此可以写出数据表格如下:
时间 | 用水 |
1 | 5 |
2 | 5+4=9 |
3 | 4+6=10 |
4 | 6 |
5 | 6 |
6 | 6 |
7 | 6 |
8 | 6 |
9 | 6 |
第四个人数据,从第 2 分钟开始到第 3 分钟结束,每分钟使用 1 升。因此可以写出数据表格如下:
时间 | 用水 |
1 | 5 |
2 | 5+4+1=10 |
3 | 4+6=10 |
4 | 6 |
5 | 6 |
6 | 6 |
7 | 6 |
8 | 6 |
9 | 6 |
从表格数据可以看出,热水器可以供应的用水。所以输出 Yes。
题目分析
从上面的数据分析可以看出,本题是一个模拟题。因此我们可以设计出最简单的算法思路如下:
i 从 1 到 n 循环 {
读取第 i 个用户的数据
j 从 si 到 ti 循环 {
当前用水数据加上 Pi
如果当前用水数据超过 W, 输出 No,结束
}
}
输出 Yes
上面的算法设计可以看出,在最坏的情况下,时间复杂度将是 O(N^2) 级别。
根据提供的样例数据,N 的最大值是 2e5,Si 的最小值为 0,Ti 的最大值为 2e5,那么需要计算的最大数据为 2e5*(2e5-0+1)=2e10。这个数据级别对于 O(N^2) 的算法而言,太大了。肯定是 TLE。
从上面的算法看,我们可以看出主要的计算量在于对 Si 到 Ti 这段数据都加上 Pi,这里需要计算 N 次。因此优化的目标在这里。
看上去是不是又非常的熟悉,不错,又是前缀和概念。这样我们可以使用前缀和对算法进行优化,优化后,算法从 O(N^2) 降低到 O(N)。
在于对 Si 到 Ti 这段数据都加上 Pi,根据前缀和的概念,相当于在 sums[si]+=p, sums[ti]-=p。
AC 参考代码
//https://atcoder.jp/contests/abc183/tasks/abc183_d
//D - Water Heater
#include <bits/stdc++.h>
using namespace std;
const int MAXN=2e5+4;
long long nums[MAXN];
int main() {
#if 1
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
#endif
int n,w;
cin>>n>>w;
for (int i=1; i<=n; i++) {
int s,t,p;
cin>>s>>t>>p;
nums[s] += p;
nums[t] -= p;
}
for (int i=1; i<MAXN; i++) {
nums[i] += nums[i-1];
}
for (int i=0; i<MAXN; i++) {
if (nums[i]>w) {
cout<<"No\n";
return 0;
}
}
cout<<"Yes\n";
return 0;
}
时间复杂度
O(N)
空间复杂度
O(N)