#include <cstdio> #include <string> #include <utility> #include <map> #include <vector> #include <algorithm> using namespace std; typedef pair<int, int> edge; // first - cost, second - first point typedef long long ll; const int SIZE = 500005; ll sum_left[SIZE], sum_right[SIZE]; vector<edge> edges; vector<int> points; int n, k; struct Range { int end; ll sub_left, sub_right; }; map<int, Range> divs; int main() { scanf("%d", &n); int v; int last_pos = -1; int total_cost = 0; for (int i = 0; i < n; ++i) { scanf("%d", &v); if (v != 0) { points.push_back(v); if (points.size() > 1) { edges.push_back(edge(i - last_pos, points.size() - 2)); total_cost += edges.back().first; } last_pos = i; } } if (points.size() == 0) { printf("0\n"); return 0; } sort(edges.rbegin(), edges.rend()); sum_left[0] = points[0]; sum_right[points.size() - 1] = points.back(); for (int i = 1; i < points.size(); ++i) { sum_left[i] = sum_left[i-1] + points[i]; sum_right[points.size() - 1 - i] = sum_right[points.size() - i] + points[points.size() - 1 - i]; } if (sum_right[0] < 0) { printf("-1\n"); return 0; } // for (int i = 0; i < points.size(); ++i) { // printf("Point %d: %d [sum_left: %lld sum_right: %lld]\n", i, points[i], sum_left[i], sum_right[i]); // } // for (int i = 0; i < edges.size(); ++i) { // printf("Edge: [%d, %d] - %d\n", edges[i].second, edges[i].second + 1, edges[i].first); // } { Range r; r.end = points.size() - 1; r.sub_left = 0; r.sub_right = 0; divs[0] = r; } for (int i = 0; i < edges.size(); ++i) { int edge_from = edges[i].second; int edge_to = edge_from + 1; int cost = edges[i].first; // printf("Processing edge: [%d, %d]: %d\n", edge_from, edge_to, cost); map<int, Range>::iterator it = divs.upper_bound(edge_from); --it; Range &r = it->second; // printf("Found range [%d, %d], (sub_left = %lld, sub_right = %lld)\n", it->first, r.end, r.sub_left, r.sub_right); if (sum_right[edge_to] - r.sub_right >= 0 && sum_left[edge_from] - r.sub_left >= 0) { // printf("Range is splitable\n"); total_cost -= cost; Range right_range; right_range.end = r.end; right_range.sub_left = sum_left[edge_from]; right_range.sub_right = r.sub_right; divs[edge_to] = right_range; r.end = edge_from; r.sub_right = sum_right[edge_to]; } } printf("%d\n", total_cost); 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 95 96 | #include <cstdio> #include <string> #include <utility> #include <map> #include <vector> #include <algorithm> using namespace std; typedef pair<int, int> edge; // first - cost, second - first point typedef long long ll; const int SIZE = 500005; ll sum_left[SIZE], sum_right[SIZE]; vector<edge> edges; vector<int> points; int n, k; struct Range { int end; ll sub_left, sub_right; }; map<int, Range> divs; int main() { scanf("%d", &n); int v; int last_pos = -1; int total_cost = 0; for (int i = 0; i < n; ++i) { scanf("%d", &v); if (v != 0) { points.push_back(v); if (points.size() > 1) { edges.push_back(edge(i - last_pos, points.size() - 2)); total_cost += edges.back().first; } last_pos = i; } } if (points.size() == 0) { printf("0\n"); return 0; } sort(edges.rbegin(), edges.rend()); sum_left[0] = points[0]; sum_right[points.size() - 1] = points.back(); for (int i = 1; i < points.size(); ++i) { sum_left[i] = sum_left[i-1] + points[i]; sum_right[points.size() - 1 - i] = sum_right[points.size() - i] + points[points.size() - 1 - i]; } if (sum_right[0] < 0) { printf("-1\n"); return 0; } // for (int i = 0; i < points.size(); ++i) { // printf("Point %d: %d [sum_left: %lld sum_right: %lld]\n", i, points[i], sum_left[i], sum_right[i]); // } // for (int i = 0; i < edges.size(); ++i) { // printf("Edge: [%d, %d] - %d\n", edges[i].second, edges[i].second + 1, edges[i].first); // } { Range r; r.end = points.size() - 1; r.sub_left = 0; r.sub_right = 0; divs[0] = r; } for (int i = 0; i < edges.size(); ++i) { int edge_from = edges[i].second; int edge_to = edge_from + 1; int cost = edges[i].first; // printf("Processing edge: [%d, %d]: %d\n", edge_from, edge_to, cost); map<int, Range>::iterator it = divs.upper_bound(edge_from); --it; Range &r = it->second; // printf("Found range [%d, %d], (sub_left = %lld, sub_right = %lld)\n", it->first, r.end, r.sub_left, r.sub_right); if (sum_right[edge_to] - r.sub_right >= 0 && sum_left[edge_from] - r.sub_left >= 0) { // printf("Range is splitable\n"); total_cost -= cost; Range right_range; right_range.end = r.end; right_range.sub_left = sum_left[edge_from]; right_range.sub_right = r.sub_right; divs[edge_to] = right_range; r.end = edge_from; r.sub_right = sum_right[edge_to]; } } printf("%d\n", total_cost); return 0; } |