Submission #1300828

#TimeUsernameProblemLanguageResultExecution timeMemory
1300828baotoan655Sparklers (JOI17_sparklers)C++20
0 / 100
1 ms572 KiB
#include <iostream> #include <vector> #include <algorithm> using namespace std; // Sử dụng __int128_t để tránh tràn số (vì v*T*i có thể lên tới 10^23) typedef __int128_t int128; int N, K; long long T_long; vector<long long> X_long; // Hàm kiểm tra với vận tốc tương đối v_rel (v_rel = 2 * Speed) bool check(long long v_val) { int128 v_rel = (int128)v_val; int128 T = (int128)T_long; // Tạo mảng A với kiểu dữ liệu lớn // Công thức đúng: A[i] = X[i] - v_rel * T * i // Điều kiện hợp lệ giữa 2 điểm i, j (i < j): Xj - Xi <= v_rel * T * (j - i) // <=> Xj - v_rel * T * j <= Xi - v_rel * T * i // <=> A[j] <= A[i] vector<int128> A(N + 1); for (int i = 1; i <= N; i++) { A[i] = (int128)X_long[i] - v_rel * T * i; } int l = K; int r = K; // Block Greedy: Mở rộng ra 2 phía // A[l] đóng vai trò "nguồn cấp" (cần lớn) // A[r] đóng vai trò "nhu cầu" (cần nhỏ) // Điều kiện duy trì: A[l_effective] >= A[r_effective] while (l > 1 || r < N) { bool moved = false; // Thử mở rộng sang TRÁI if (l > 1) { int curr = l - 1; int128 min_val = A[curr]; // Tìm điểm hồi phục bên trái while (curr > 1 && A[curr] < A[l]) { if (A[curr] < min_val) min_val = A[curr]; curr--; } // Nếu tìm thấy chuỗi block trái mà điểm yếu nhất (min_val) vẫn >= A[r] // thì block này hợp lệ. if (min_val >= A[l]) min_val = A[l]; // Cập nhật lại min nếu chỉ đi 1 bước // Logic chuẩn: min_val phải lớn hơn hoặc bằng A[r] // Tuy nhiên, logic while ở trên dừng khi A[curr] >= A[l], tức là đã tìm thấy đỉnh mới. // Ta cần kiểm tra min_val của cả đoạn vừa đi qua. // Viết lại logic duyệt cho rõ ràng hơn: int next_l = l - 1; int128 current_min = A[next_l]; while (next_l > 1 && A[next_l] < A[l]) { // Đang ở thung lũng, cố đi tiếp để tìm đỉnh cao hơn next_l--; if (A[next_l] < current_min) current_min = A[next_l]; } // Kiểm tra điều kiện hợp lệ với biên phải hiện tại if (current_min >= A[r]) { l = next_l; // Nhảy cóc tới vị trí mới moved = true; } } // Thử mở rộng sang PHẢI if (r < N) { int curr = r + 1; int128 max_val = A[curr]; int next_r = r + 1; int128 current_max = A[next_r]; while (next_r < N && A[next_r] > A[r]) { // Đang ở ngọn đồi, cố đi tiếp để tìm thung lũng thấp hơn next_r++; if (A[next_r] > current_max) current_max = A[next_r]; } // Kiểm tra điều kiện hợp lệ với biên trái hiện tại if (current_max <= A[l]) { r = next_r; moved = true; } } if (!moved) return false; // Ưu tiên: Nếu cả 2 đều đi được thì sao? // Logic trên thực hiện tuần tự, nếu trái đi được thì l đã thay đổi. // Sau đó kiểm tra phải với l mới. Điều này vẫn đúng đắn (tham lam). } return true; } int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); if (cin >> N >> K >> T_long) { X_long.resize(N + 1); for (int i = 1; i <= N; i++) { cin >> X_long[i]; } long long low = 0, high = 1000000000000000LL; // 10^15 long long ans = high; while (low <= high) { long long mid = low + (high - low) / 2; if (check(mid)) { ans = mid; high = mid - 1; } else { low = mid + 1; } } cout << (ans + 1) / 2 << endl; } return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...