You are on page 1of 3

Nhận xét: Vì John cố gắng tới D sớm nhất nên trong phương án tối

ưu, John sẽ chọn những chuyến xe sớm nhất.

Từ đây, ta thấy, các cách chọn của Wick có dạng như sau:
- Loại bỏ một số chuyến xe đầu tiên xuất phát từ A, tạm gọi con
số này là x, khi đó John sẽ bắt chuyến xe thứ x + 1 xuất phát từ
A.
- Ngay sau khi đến B vào thời điểm a(x + 1) + ta, lưu ý ở đây,
Wick không được phép hủy chuyến xe nào xuất phát từ B, nên
John ngay lập tức bắt chuyến xe by nhỏ nhất thỏa mãn điều kiện
by >= a(x + 1) + ta.
- Giả sử Wick không được phá hủy chuyến nào ở C, chuyến xe
tiếp theo mà John bắt sẽ là cz nhỏ nhất thỏa mãn cz >= by + tb,
tuy nhiên Wick vẫn còn k - x lượt phá hủy, John sẽ phải bắt
chuyến xe c(z + k - x) và đến D vào thời điểm c(z + k -x) + tc.
Vì vậy, ta hoàn toàn có thể duyệt x và sử dụng thuật toán Two Pointer
hoặc Binary Search để tìm kiếm y và z thích hợp.
Ngoài ra còn có một lưu ý nhỏ, nếu như k >= min(na, nc) thì kết quả
ngay lập tức là -1 do chặn hết.

Source Code:

#include <bits/stdc++.h>
using namespace std;

int main() {
ios :: sync_with_stdio(0);
cin.tie (0); cout.tie(0);

int nA, nB, nC, tA, tB, tC, k;


cin >> nA >> nB >> nC >> tA >> tB >> tC >> k;
vector <int> a(nA), b(nB), c(nC);
for (int &x: a) cin >> x;
for (int &x: b) cin >> x;
for (int &x: c) cin >> x;

if (k >= min(nA, nC)) {


cout << -1 << '\n';
return 0;
}

vector <int> nxtC(nB);


for (int i = 0, j = 0; i < nB; i++) {
while (j < nC && c[j] < b[i] + tB) j++;
nxtC[i] = j;
}

int res = -1;


for (int i = 0, j = 0; i < nA; i++) {
if (i > k) break;
while (j < nB && b[j] < a[i] + tA) j++;
if (j < nB && nxtC[j] + k - i < nC) {
res = max(res, c[nxtC[j] + k - i] + tC);
}
else {
cout << -1 << '\n';
return 0;
}
}

cout << res << '\n';

return 0;
}

You might also like