Submission #607168

#TimeUsernameProblemLanguageResultExecution timeMemory
607168jophyyjhSure Bet (CEOI17_sure)C++14
100 / 100
1715 ms5192 KiB
/** * Notes during contest. * * ------ A ------ * Looks like that it's about strongly-connected components, cycles or bridges. I * think we can detect all cycles and merge all those nodes into one. The resulting * graph would be a tree, so we can then use a difference array to find each edge's * direction. Note that any edge in a cycle is B, and any edge not in cycles is a * "bridge". * !IMPORTANT! (Reminded by tinjyu during contest) !IMPORTANT! * Graph may not be CONNECTED. * * ------ B ------ * We iterate through all cost k. We can take at most k bets. If we can guarantee * a profit of p, min(#A_is_the_outcome, #B_is_the_outcome) >= p + k. Binary search * is ok. * For each k, we wanna find the max achievable for * min(#A_is_outcome, #B_is_outcome) - k. * * ------ C ------ * We have a tree in which a mouse runs. [S1] is just a brute-force. * * Time Complexity 1: O(n + m + p * log(n)) * Time Complexity 2: O(n * log(n * VAL_MAX) * log(n)) * Time Complexity 3: O() * Implementation 1 */ #include <bits/stdc++.h> typedef int64_t int_t; typedef std::vector<int_t> vec; const double INF = 1e9; const double VAL_MAX = 1e4; int main() { std::ios_base::sync_with_stdio(false); std::cin.tie(NULL); int_t n; std::cin >> n; std::vector<double> A(n), B(n); for (int_t k = 0; k < n; k++) std::cin >> A[k] >> B[k]; std::sort(A.rbegin(), A.rend()); std::sort(B.rbegin(), B.rend()); std::vector<double> A_prefix(n + 1), B_prefix(n + 1); A_prefix[0] = B_prefix[0] = 0; for (int_t k = 0; k < n; k++) A_prefix[k + 1] = A_prefix[k] + A[k], B_prefix[k + 1] = B_prefix[k] + B[k]; double profit = -INF; for (int_t cost = 0; cost <= 2 * n; cost++) { double min = 0; for (double step_m = n * VAL_MAX; step_m >= 0.000005; step_m /= 2) { for (;;) { double new_min = min + step_m; int_t A_used = n + 1; for (int_t step = n / 2 + 1; step >= 1; step /= 2) { while (A_used - step >= 0 && A_prefix[A_used - step] >= new_min) A_used -= step; } int_t B_used = n + 1; for (int_t step = n / 2 + 1; step >= 1; step /= 2) { while (B_used - step >= 0 && B_prefix[B_used - step] >= new_min) B_used -= step; } if (A_used == n + 1 || B_used == n + 1) break; if (A_used + B_used <= cost) min = new_min; else break; } } // std::cerr << "[debug] " << cost << ": " << std::fixed << min << std::endl; profit = std::max(profit, min - cost); } std::cout << std::fixed << std::setprecision(4) << profit << '\n'; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...