#include <cstdio> #include <vector> #define DEBUG false using namespace std; bool check_onehouse_possibility(long long target_val, long long lefts, long long rights, long long centers) { // l, r, c maximum values are about 2e5, so their product is 8e15 which fits into a long long int // we need some big long long care here long long total_res = lefts * rights * centers; total_res += (lefts + rights) * centers * (centers - 1) / 2; total_res += centers * (centers - 1) * (centers - 2) / 6; if constexpr (DEBUG) { if (total_res >= target_val) { printf("Possible (%lld)\n", total_res); } else { printf("Impossible (%lld)\n", total_res); } } return total_res >= target_val; } bool check_score_possibility(const vector<long long> &houses, long long target_score) { long long remaining_right = target_score; long long used_left = 0LL; for (int i = 0; i < houses.size(); ++i) { long long target_val = houses[i]; if constexpr(DEBUG) printf("Filling house %2d\n", i); if constexpr(DEBUG) printf("Trying to get %6lld from %6lld L | %6lld C | %6lld R\n", target_val, used_left, remaining_right, 0LL); if (remaining_right < 1LL || !check_onehouse_possibility(target_val, used_left, 0LL, remaining_right)) return false; if (i == houses.size() - 1) return true; // we don't need to find min value for last house long long max_center = remaining_right; long long min_center = 1; while (min_center != max_center) { // max_center will always work // (min_center - 1) will never work long long check_center = (min_center + max_center) / 2; long long stay_right = remaining_right - check_center; if constexpr(DEBUG) printf("Trying to get %6lld from %6lld L | %6lld C | %6lld R\n", target_val, used_left, check_center, stay_right); bool possible = check_onehouse_possibility(target_val, used_left, stay_right, check_center); if (possible) { max_center = check_center; } else { min_center = check_center + 1; } } used_left += min_center; remaining_right -= min_center; } return true; } int main() { int t; scanf("%d", &t); for (int t_i = 0; t_i < t; ++t_i) { int n; scanf("%d", &n); vector<long long> houses; for (int i = 0; i < n; ++i) { int x; scanf("%d", &x); if (x != 0) { houses.push_back(x); } } n = static_cast<int>(houses.size()); if (n == 0) { printf("0\n"); continue; } long long max_score = n + 2000 + 2; // 1 in each occupied house, +1001 in each edge house allowing for at least 1e6 matches in every house long long min_score = 1; while(min_score != max_score) { // (max_score) will always 100% work // (min_score - 1) will always 100% not work long long check_score = (min_score + max_score) / 2LL; bool is_enough = check_score_possibility(houses, check_score); if (is_enough) { if constexpr(DEBUG) printf("Score %8lld is enough\n", check_score); max_score = check_score; } else { if constexpr(DEBUG) printf("Score %8lld is NOT enough\n", check_score); min_score = check_score + 1; } } printf("%lld\n", min_score); } return 0; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | #include <cstdio> #include <vector> #define DEBUG false using namespace std; bool check_onehouse_possibility(long long target_val, long long lefts, long long rights, long long centers) { // l, r, c maximum values are about 2e5, so their product is 8e15 which fits into a long long int // we need some big long long care here long long total_res = lefts * rights * centers; total_res += (lefts + rights) * centers * (centers - 1) / 2; total_res += centers * (centers - 1) * (centers - 2) / 6; if constexpr (DEBUG) { if (total_res >= target_val) { printf("Possible (%lld)\n", total_res); } else { printf("Impossible (%lld)\n", total_res); } } return total_res >= target_val; } bool check_score_possibility(const vector<long long> &houses, long long target_score) { long long remaining_right = target_score; long long used_left = 0LL; for (int i = 0; i < houses.size(); ++i) { long long target_val = houses[i]; if constexpr(DEBUG) printf("Filling house %2d\n", i); if constexpr(DEBUG) printf("Trying to get %6lld from %6lld L | %6lld C | %6lld R\n", target_val, used_left, remaining_right, 0LL); if (remaining_right < 1LL || !check_onehouse_possibility(target_val, used_left, 0LL, remaining_right)) return false; if (i == houses.size() - 1) return true; // we don't need to find min value for last house long long max_center = remaining_right; long long min_center = 1; while (min_center != max_center) { // max_center will always work // (min_center - 1) will never work long long check_center = (min_center + max_center) / 2; long long stay_right = remaining_right - check_center; if constexpr(DEBUG) printf("Trying to get %6lld from %6lld L | %6lld C | %6lld R\n", target_val, used_left, check_center, stay_right); bool possible = check_onehouse_possibility(target_val, used_left, stay_right, check_center); if (possible) { max_center = check_center; } else { min_center = check_center + 1; } } used_left += min_center; remaining_right -= min_center; } return true; } int main() { int t; scanf("%d", &t); for (int t_i = 0; t_i < t; ++t_i) { int n; scanf("%d", &n); vector<long long> houses; for (int i = 0; i < n; ++i) { int x; scanf("%d", &x); if (x != 0) { houses.push_back(x); } } n = static_cast<int>(houses.size()); if (n == 0) { printf("0\n"); continue; } long long max_score = n + 2000 + 2; // 1 in each occupied house, +1001 in each edge house allowing for at least 1e6 matches in every house long long min_score = 1; while(min_score != max_score) { // (max_score) will always 100% work // (min_score - 1) will always 100% not work long long check_score = (min_score + max_score) / 2LL; bool is_enough = check_score_possibility(houses, check_score); if (is_enough) { if constexpr(DEBUG) printf("Score %8lld is enough\n", check_score); max_score = check_score; } else { if constexpr(DEBUG) printf("Score %8lld is NOT enough\n", check_score); min_score = check_score + 1; } } printf("%lld\n", min_score); } return 0; } |