题目描述
难度分:1600
输入n、m(1≤n,m≤2×105)、ta、 tb(1≤ta,tb≤109)、k(1≤k≤n+m),长为n的严格递增数组a(1≤a[i]≤109)和长为m的严格递增数组b(1≤b[i]≤109)。
从A
地飞往B
地的航班有n个,第i个航班的起飞时刻为 a[i],航行时间为ta。
从B
地飞往C
地的航班有m个,第i个航班的起飞时刻为 b[i],航行时间为tb。
转机时间忽略不计。
你可以禁止掉其中的k个航班。最大化到达C
的最早(最小)时刻。如果可以让人无法到达C
,输出−1。
输入样例1
4 5 1 1 2
1 3 5 7
1 2 3 9 10
输出样例1
11
输入样例2
2 2 4 4 2
1 10
10 20
输出样例2
-1
输入样例3
4 3 2 3 1
1 999999998 999999999 1000000000
3 4 1000000000
输出样例3
1000000003
算法
双指针
首先k≥n时,把所有的A
飞B
航班删除就肯定到不了C
了,答案为−1。
直觉上就可以找到一个很有道理的贪心思路,就是尽可能删除A
到B
早的航班。假设a[i]是第一个未被删除的A
到B
航班,那么就还剩下j=k−(i−1)个航班可以删除,这时候会有些比较早的B
到C
航班是肯定赶不上的,即这些航班的起飞时间小于a[i]+ta。
假设最早能够赶上的B
飞C
航班是b[index],那么就可以删除b[index…index+j−1]的航班。则此时的答案就是b[index+j]+tb,如果index+j>m,说明剩下的B
飞C
航班全部可以删掉,直接就到不了C
了,答案为−1。
最后我们发现i越靠右,那相应的index也是越靠右的,所以指针不回退,双指针算法就能算出答案。
复杂度分析
时间复杂度
枚举删除A
到B
的航班需要遍历i∈[1,k+1],在最差情况下k可以达到n,因此时间复杂度为O(n)。而index指针需要遍历[0,m],时间复杂度是O(m)。综上,双指针算法的整体时间复杂度就是O(n+m)。
空间复杂度
除了输入的几个数组,仅使用了有限几个变量,因此额外空间复杂度为O(1)。
C++ 代码
#include <bits/stdc++.h>
using namespace std;
const int N = 200010;
int n, m, ta, tb, k, a[N], b[N];
int main() {
scanf("%d%d%d%d%d", &n, &m, &ta, &tb, &k);
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
for(int i = 1; i <= m; i++) {
scanf("%d", &b[i]);
}
if(k >= n) {
puts("-1");
}else {
int ans = 0;
// 枚举删掉A到B的航班数
for(int i = 1, index = 0; i <= k + 1; i++) {
int j = k - (i - 1); // 删掉B到C的航班数
while(index <= m && b[index] < a[i] + ta) {
index++;
}
if(index + j > m) {
ans = -1;
break;
}else {
ans = max(ans, b[index + j] + tb);
}
}
printf("%d\n", ans);
}
return 0;
}