제출 #1172239

#제출 시각아이디문제언어결과실행 시간메모리
1172239jillCake 3 (JOI19_cake3)C++20
0 / 100
85 ms219712 KiB
#include <bits/stdc++.h> using namespace std; #define fi first #define se second using ll = long long; using pii = pair<ll, ll>; const ll maxn = 4000005, inf = 1000000000, oo = 1000000000000000000LL; ll n, m, dp[2][maxn]; pii a[maxn]; struct WT { struct node { int l, r; vector<ll> x; vector<ll> s; } t[maxn]; int build(vector<ll> &seq, ll A = 0, ll B = inf) { static int idxNode = 0; if (seq.empty()) return -1; int cur = idxNode++; t[cur].x.assign(seq.size(), 0); t[cur].s.assign(seq.size(), 0); if (A == B) return cur; ll mid = (A + B) / 2; vector<ll> left_seq, right_seq; for (int i = 0; i < (int)seq.size(); i++) { if (seq[i] <= mid) { left_seq.push_back(seq[i]); } else { t[cur].x[i] = 1; t[cur].s[i] = seq[i]; right_seq.push_back(seq[i]); } } for (int i = (int)seq.size() - 2; i >= 0; i--) { t[cur].x[i] += t[cur].x[i + 1]; t[cur].s[i] += t[cur].s[i + 1]; } t[cur].l = build(left_seq, A, mid); t[cur].r = build(right_seq, mid + 1, B); return cur; } int map_left(int nd, int i) { return i >= 0 ? i - t[nd].x[i] : -1; } int map_right(int nd, int i) { return i >= 0 ? t[nd].x[i] - 1 : -1; } int countRight(int cur, int l, int r) { if (l > r) return 0; ll totalR = t[cur].x[l]; ll beyond = (r + 1 < (int)t[cur].x.size()) ? t[cur].x[r + 1] : 0; return (int)(totalR - beyond); } ll sumRight(int cur, int l, int r) { if (l > r) return 0LL; ll totalR = t[cur].s[l]; ll beyond = (r + 1 < (int)t[cur].s.size()) ? t[cur].s[r + 1] : 0LL; return totalR - beyond; } ll queryUtil(int node, int A, int B, int l, int r, int k) { if (node == -1 || l > r || k <= 0) return 0LL; if (A == B) { int countSeg = (r - l + 1); int take = min(countSeg, k); return 1LL * take * A; } int mid = (A + B) >> 1; int totalR = countRight(node, l, r); if (totalR >= k) { int newL = map_right(node, l - 1) + 1; int newR = map_right(node, r); return queryUtil(t[node].r, mid + 1, B, newL, newR, k); } else { ll sumR = sumRight(node, l, r); int newL = map_left(node, l - 1) + 1; int newR = map_left(node, r); return sumR + queryUtil(t[node].l, A, mid, newL, newR, k - totalR); } } ll query(int l, int r, int k) { if (l > r) return 0LL; return queryUtil(0, 0, inf, l, r, k); } } tree; vector<ll> b; void calc(int x, int l, int r, int opl, int opr) { stack<tuple<int, int, int, int>> st; st.push({l, r, opl, opr}); while (!st.empty()) { auto [L, R, opL, opR] = st.top(); st.pop(); if (L > R) continue; int mid = (L + R) >> 1; pii best = {-oo, -1}; int limit = min(mid - 1, opR); for (int k = opL; k <= limit; k++) { ll candidate = tree.query(k + 1, mid - 1, m - 2) + a[mid].fi + a[k].fi - 2 * abs(a[mid].se - a[k].se); best = max(best, {candidate, k}); } dp[x][mid] = best.fi; int opt = best.se; st.push({L, mid - 1, opL, opt}); st.push({mid + 1, R, opt, opR}); } } signed main() { ios::sync_with_stdio(false); cin.tie(nullptr); cin >> n >> m; for (int i = 0; i < n; i++) { cin >> a[i].fi >> a[i].se; } sort(a, a + n, [](const pii &x, const pii &y) { return x.se < y.se; }); for (int i = 0; i < n; i++) { dp[0][i] = a[i].fi - a[i].se; b.push_back(a[i].fi); } tree.build(b); calc(1, 0, n - 1, 0, n - 1); cout << *max_element(dp[1], dp[1] + n); return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...