题目描述
⼩Y同学有⼀块超级CPU,它有两个超级核⼼A和B。
A核⼼可以同时处理多项任务,每项任务处理时间为x,B核⼼只能同时处理⼀项任务,每项任务处理时间为y。
这⼀天,⼩Y同学接到了n项紧急任务,第i项紧急任务在ti时刻发出,且必须在任务发出时进⾏处理。
由于⼩Y可以调节CPU的B核⼼,你想知道对于y∈1,x,处理完毕所有任务的最早时间是多少?
输入格式
第⼀⾏两个整数n,x,表⽰紧急任务数量及A核⼼对每项任务的处理时间。 第⼆⾏n个整数ti,表⽰第i个紧急任务发出的时间ti。
输出格式
共x⾏:第i(1≤i≤x)⾏⼀个整数,表⽰当y=i时的答案ans。
数据范围与提示
样例输入输出1解释:
y=1的时候:t1=1任务交给核⼼A,t2=2,t3=3两个任务交给核⼼B,结束时刻是4,这是最早的⼀种完成的⽅案。
y=2的时候:t1=1,t3=3两个任务交给核⼼B,t2=2任务交给核⼼A,结束时刻是5,这是最早的⼀种完成的⽅案。
y=3的时候:t1=1,t2=2两个任务交给核⼼A,t3=3任务交给核⼼B,结束时刻是6,这是最早的⼀种完成的⽅案。
对于40%的数据,1 ≤ n ≤ 103
对于100%的数据,1 ≤ n, x ≤ 106, 0 ≤ ti-1 ≤ ti ≤ 109
Sample Input 1
3 3
1 2 3
Sample Output 1
4
5
6
Sample Input 2
3 5
1 4 5
Sample Output 2
6
9
9
9
10
首先拿到这道题,第一感觉就是题面好奇怪,莫名让我无从下手。。。(可能最近板题做多了) 略加思索后,锁定贪心
首先,由题意可知,当B不空闲的时候,是一定会选择A的;由于题目保证y∈1,x,所以,把最后一位甩给B去处理一定不劣于甩个A去处理,因此,我们想到可以倒着贪心,先判断最后一位,再判断倒数第二位,找到一次到不满足可以甩给B及时处理的条件(即,y>t[i] - t[i - 1]),在此之前的任务甩A甩B并不重要。
由此得到比较暴力的贪心,时间复杂度O(n)
但我们看题目给的数据范围,对于100%的数据,1 ≤ n, x ≤ 106, 0 ≤ ti-1 ≤ ti ≤ 109,用O(n)的时间是一定A不了的,因此,我们考虑优化。
我们发现,每次计算不同的x的时候,我们会重复计算两个时间点之间的差值,但我们完全可以存下差值,剩下重复计算的时间,进一步引发我们的思考:怎样用O(1)的时间访问到从后往前数,第一个不满足B处理一个用时x的条件的点。
很直接,用数组存,然后用类似后缀和的方式,处理一段,这样一来,差值计算用O(n)的时间,存下标用O(n)的时间,总共用O(n)的时间,就不会TLE了
#include
#include
using namespace std;
const int N = 1e6;
int n, x, t[N + 5], ip[N + 5];
inline int count (const int idx) {
return max (t[ip[idx]] + x, t[n] + idx);
}
int main () {
scanf ("%d %d", &n, &x);
for (int i = 1; i <= n; ++ i)
scanf ("%d", &t[i]);
for (int i = n - 1; i >= 1; -- i) {
int dif = t[i + 1] - t[i];
++ dif;
for (int j = dif; j <= x && ip[j] == 0; ++ j)
ip[j] = i;
//也可以用while来写,貌似会快一些。。。
}
t[0] = -x;
for (int i = 1; i <= x; ++ i) {
int ans = count (i);
printf ("%d\n", ans);
}
return 0;
}