#include <stdint.h> #include <iostream> #include <algorithm> #include <vector> using namespace std; struct Cut { int64_t d, b; int p; Cut(): d(0), b(0), p(0) { } Cut(int64_t const &d, int64_t const &b, int const &p): d(d), b(b), p(p) { } ~Cut() { } }; int last_cut(vector<Cut> const &cuts, int const &p) { // last cut where c.p <= p int l0 = 0; int l1 = cuts.size() - 1; if(cuts[l1].p <= p) return l1; if(not (cuts[l0].p <= p)) return -1; // damn impossible while(l1 != l0) { int lh = (l0 + l1 + 1) / 2; if(cuts[lh].p <= p) l0 = lh; else l1 = lh - 1; } return l0; } bool is_sufficient(Cut const &c, vector<int64_t> const &growth, int const &p, vector<Cut> const &cuts) { int l = last_cut(cuts, p); int64_t val = cuts[l].b + (c.d - cuts[l].d) * growth[p]; return val > c.b; } int first_sufficient(Cut const &c, vector<int64_t> const &growth, vector<Cut> const &cuts) { int p0 = 0; int p1 = growth.size() - 1; if(is_sufficient(c, growth, p0, cuts)) return p0; if(not is_sufficient(c, growth, p1, cuts)) return p1 + 1; while(p1 != p0) { int ph = (p0 + p1) / 2; if(is_sufficient(c, growth, ph, cuts)) p1 = ph; else p0 = ph + 1; } return p0; } int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); int n, m; cin >> n >> m; vector<int64_t> growth(n); for(int i = 0; i < n; ++i) cin >> growth[i]; sort(growth.begin(), growth.end()); vector<int64_t> gSum(n+1); gSum[n] = 0; gSum[n-1] = growth[n-1]; for(int i = n - 2; i >= 0; --i) gSum[i] = growth[i] + gSum[i + 1]; // cerr << "growth = "; for(int i = 0; i < n; ++i) cerr << growth[i] << ' '; cerr << '\n'; // cerr << "gSum = "; for(int i = 0; i < n; ++i) cerr << gSum[i] << ' '; cerr << '\n'; vector<Cut> cuts; cuts.push_back(Cut()); for(int j = 0; j < m; ++j) { Cut c; cin >> c.d >> c.b; c.p = first_sufficient(c, growth, cuts); // cerr << "p = " << c.p << '\n'; int64_t r = 0; int prevP = n; while(not cuts.empty() and cuts.back().p >= c.p) { r += cuts.back().b * (prevP - cuts.back().p) + (c.d - cuts.back().d) * (gSum[cuts.back().p] - gSum[prevP]) - c.b * (prevP - cuts.back().p); // cout << "removing cut " << cuts.back().d << ' ' << cuts.back().b << ' ' << cuts.back().p << '\n'; prevP = cuts.back().p; cuts.pop_back(); } if(not cuts.empty()) { r += cuts.back().b * (prevP - c.p) + (c.d - cuts.back().d) * (gSum[c.p] - gSum[prevP]) - c.b * (prevP - c.p); } cuts.push_back(c); cout << r << '\n'; } 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 | #include <stdint.h> #include <iostream> #include <algorithm> #include <vector> using namespace std; struct Cut { int64_t d, b; int p; Cut(): d(0), b(0), p(0) { } Cut(int64_t const &d, int64_t const &b, int const &p): d(d), b(b), p(p) { } ~Cut() { } }; int last_cut(vector<Cut> const &cuts, int const &p) { // last cut where c.p <= p int l0 = 0; int l1 = cuts.size() - 1; if(cuts[l1].p <= p) return l1; if(not (cuts[l0].p <= p)) return -1; // damn impossible while(l1 != l0) { int lh = (l0 + l1 + 1) / 2; if(cuts[lh].p <= p) l0 = lh; else l1 = lh - 1; } return l0; } bool is_sufficient(Cut const &c, vector<int64_t> const &growth, int const &p, vector<Cut> const &cuts) { int l = last_cut(cuts, p); int64_t val = cuts[l].b + (c.d - cuts[l].d) * growth[p]; return val > c.b; } int first_sufficient(Cut const &c, vector<int64_t> const &growth, vector<Cut> const &cuts) { int p0 = 0; int p1 = growth.size() - 1; if(is_sufficient(c, growth, p0, cuts)) return p0; if(not is_sufficient(c, growth, p1, cuts)) return p1 + 1; while(p1 != p0) { int ph = (p0 + p1) / 2; if(is_sufficient(c, growth, ph, cuts)) p1 = ph; else p0 = ph + 1; } return p0; } int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); int n, m; cin >> n >> m; vector<int64_t> growth(n); for(int i = 0; i < n; ++i) cin >> growth[i]; sort(growth.begin(), growth.end()); vector<int64_t> gSum(n+1); gSum[n] = 0; gSum[n-1] = growth[n-1]; for(int i = n - 2; i >= 0; --i) gSum[i] = growth[i] + gSum[i + 1]; // cerr << "growth = "; for(int i = 0; i < n; ++i) cerr << growth[i] << ' '; cerr << '\n'; // cerr << "gSum = "; for(int i = 0; i < n; ++i) cerr << gSum[i] << ' '; cerr << '\n'; vector<Cut> cuts; cuts.push_back(Cut()); for(int j = 0; j < m; ++j) { Cut c; cin >> c.d >> c.b; c.p = first_sufficient(c, growth, cuts); // cerr << "p = " << c.p << '\n'; int64_t r = 0; int prevP = n; while(not cuts.empty() and cuts.back().p >= c.p) { r += cuts.back().b * (prevP - cuts.back().p) + (c.d - cuts.back().d) * (gSum[cuts.back().p] - gSum[prevP]) - c.b * (prevP - cuts.back().p); // cout << "removing cut " << cuts.back().d << ' ' << cuts.back().b << ' ' << cuts.back().p << '\n'; prevP = cuts.back().p; cuts.pop_back(); } if(not cuts.empty()) { r += cuts.back().b * (prevP - c.p) + (c.d - cuts.back().d) * (gSum[c.p] - gSum[prevP]) - c.b * (prevP - c.p); } cuts.push_back(c); cout << r << '\n'; } return 0; } |