#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; } |
English