#include <cstdio> #include <algorithm> #include <vector> using namespace std; const long long BIG = 400000000000000000ll; struct node { pair<long long, long long> p; // best unused line before time int_time bool side; // 0 means that p is a left son long long sum; // of used in the subtree int num; // of used in the subtree long long int_time; // how big .num on the left side has to be for an intersection long long p_num, p_sum; // used by p (the best function in the subtree) }; node p[1<<21]; int n; long long ans; int K = 1; bool comp1(int a, int b) { return p[a].p < p[b].p; } void fix_up(const int i, const int pos) { // 1 <= i < K, lower levels are ok for this pos (= .num on the left) p[i].sum = p[2*i].sum + p[2*i+1].sum; p[i].num = p[2*i].num + p[2*i+1].num; long long a[2]; a[0] = (pos + p[2*i].p_num) * p[2*i].p.first + p[2*i].p.second + p[2*i+1].sum + p[2*i].p_sum; a[1] = (pos + p[2*i].num + p[2*i+1].p_num) * p[2*i+1].p.first + p[2*i+1].p.second + p[2*i+1].p_sum; p[i].int_time = min(p[2*i].int_time, p[2*i+1].int_time - p[2*i].num); if (a[0] <= a[1]) { // use right p p[i].p = p[2*i+1].p; p[i].p_sum = p[2*i+1].p_sum; p[i].p_num = p[2*i].num + p[2*i+1].p_num; p[i].side = 1; } else { p[i].p = p[2*i].p; p[i].p_sum = p[2*i].p_sum + p[2*i+1].sum; p[i].p_num = p[2*i].p_num; p[i].side = 0; long long t = n; if (p[2*i].p.first < p[2*i+1].p.first) { t = ((p[2*i].p.second - p[2*i+1].p.second) + (p[2*i].p_num * p[2*i].p.first - (p[2*i].num + p[2*i+1].p_num) * p[2*i+1].p.first) + \ + (p[2*i].p_sum + p[2*i+1].sum - p[2*i+1].p_sum) + (p[2*i+1].p.first - p[2*i].p.first - 1)) / (p[2*i+1].p.first - p[2*i].p.first); } if (t <= 0 || t > n) t = n; p[i].int_time = min(t, p[i].int_time); } } int counter; void fix_int(const int i, const int pos) { // for i < K if (2*i < K && p[2*i].int_time <= pos) fix_int(2*i, pos); if (2*i+1 < K && p[2*i+1].int_time <= pos + p[2*i].num) fix_int(2*i+1, pos + p[2*i].num); fix_up(i, pos); } long long best(const int i, int pos, long long sum) { if (i >= K) { // found best ! long long a = sum + pos * p[i].p.first + p[i].p.second; p[i].sum = p[i].p.first; p[i].num = 1; p[i].p.second = -BIG; return a; } if (p[i].int_time <= pos) { fix_int(i, pos); } if (p[i].side == 0) { long long b = best(2*i, pos, sum + p[2*i+1].sum); fix_int(i, pos); return b; } else { long long b = best(2*i+1, pos + p[2*i].num, sum); fix_int(i, pos); return b; } } int main() { scanf("%d", &n); int t[n]; K = 2; while (K < n) K <<= 1; for (int i = 0; i < n; ++i) { long long a, b; scanf("%lld %lld", &a, &b); p[i].p.first = a; p[i].p.second = b; t[i] = i; } sort(t, t+n, comp1); for (int i = 0; i < n; ++i) { p[K+i].p = p[t[i]].p; p[K+i].int_time = n; } for (int i = n; i < K; ++i) { p[K+i].p.first = 1000000; p[K+i].p.second = -BIG; p[K+i].int_time = n; } for (int i = K - 1; i > 0; --i) { fix_up(i, 0); } for (int i = 0; i < n; ++i) { fix_int(1, 0); ans += best(1, 0, 0); printf("%lld\n", ans); } 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 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | #include <cstdio> #include <algorithm> #include <vector> using namespace std; const long long BIG = 400000000000000000ll; struct node { pair<long long, long long> p; // best unused line before time int_time bool side; // 0 means that p is a left son long long sum; // of used in the subtree int num; // of used in the subtree long long int_time; // how big .num on the left side has to be for an intersection long long p_num, p_sum; // used by p (the best function in the subtree) }; node p[1<<21]; int n; long long ans; int K = 1; bool comp1(int a, int b) { return p[a].p < p[b].p; } void fix_up(const int i, const int pos) { // 1 <= i < K, lower levels are ok for this pos (= .num on the left) p[i].sum = p[2*i].sum + p[2*i+1].sum; p[i].num = p[2*i].num + p[2*i+1].num; long long a[2]; a[0] = (pos + p[2*i].p_num) * p[2*i].p.first + p[2*i].p.second + p[2*i+1].sum + p[2*i].p_sum; a[1] = (pos + p[2*i].num + p[2*i+1].p_num) * p[2*i+1].p.first + p[2*i+1].p.second + p[2*i+1].p_sum; p[i].int_time = min(p[2*i].int_time, p[2*i+1].int_time - p[2*i].num); if (a[0] <= a[1]) { // use right p p[i].p = p[2*i+1].p; p[i].p_sum = p[2*i+1].p_sum; p[i].p_num = p[2*i].num + p[2*i+1].p_num; p[i].side = 1; } else { p[i].p = p[2*i].p; p[i].p_sum = p[2*i].p_sum + p[2*i+1].sum; p[i].p_num = p[2*i].p_num; p[i].side = 0; long long t = n; if (p[2*i].p.first < p[2*i+1].p.first) { t = ((p[2*i].p.second - p[2*i+1].p.second) + (p[2*i].p_num * p[2*i].p.first - (p[2*i].num + p[2*i+1].p_num) * p[2*i+1].p.first) + \ + (p[2*i].p_sum + p[2*i+1].sum - p[2*i+1].p_sum) + (p[2*i+1].p.first - p[2*i].p.first - 1)) / (p[2*i+1].p.first - p[2*i].p.first); } if (t <= 0 || t > n) t = n; p[i].int_time = min(t, p[i].int_time); } } int counter; void fix_int(const int i, const int pos) { // for i < K if (2*i < K && p[2*i].int_time <= pos) fix_int(2*i, pos); if (2*i+1 < K && p[2*i+1].int_time <= pos + p[2*i].num) fix_int(2*i+1, pos + p[2*i].num); fix_up(i, pos); } long long best(const int i, int pos, long long sum) { if (i >= K) { // found best ! long long a = sum + pos * p[i].p.first + p[i].p.second; p[i].sum = p[i].p.first; p[i].num = 1; p[i].p.second = -BIG; return a; } if (p[i].int_time <= pos) { fix_int(i, pos); } if (p[i].side == 0) { long long b = best(2*i, pos, sum + p[2*i+1].sum); fix_int(i, pos); return b; } else { long long b = best(2*i+1, pos + p[2*i].num, sum); fix_int(i, pos); return b; } } int main() { scanf("%d", &n); int t[n]; K = 2; while (K < n) K <<= 1; for (int i = 0; i < n; ++i) { long long a, b; scanf("%lld %lld", &a, &b); p[i].p.first = a; p[i].p.second = b; t[i] = i; } sort(t, t+n, comp1); for (int i = 0; i < n; ++i) { p[K+i].p = p[t[i]].p; p[K+i].int_time = n; } for (int i = n; i < K; ++i) { p[K+i].p.first = 1000000; p[K+i].p.second = -BIG; p[K+i].int_time = n; } for (int i = K - 1; i > 0; --i) { fix_up(i, 0); } for (int i = 0; i < n; ++i) { fix_int(1, 0); ans += best(1, 0, 0); printf("%lld\n", ans); } return 0; } |