Editorial for VOI 15 Bài 5 - Chia phần
Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.
Submitting an official solution before solving the problem yourself is a bannable offence.
Submitting an official solution before solving the problem yourself is a bannable offence.
Lưu ý: Các code mẫu dưới đây chỉ mang tính tham khảo và có thể không AC được bài tập này
Code mẫu của ladpro98
#include <bits/stdc++.h> const int N = 500005; const int INF = 1e9 + 9; using namespace std; struct node { int l, r; int delay; int minV, minPos; int minCnt; node *left, *right; node (int _l, int _r) { l = _l; r = _r; delay = 0; left = right = NULL; } void gatherMin() { minV = right->minV; minPos = right->minPos; if (left->minV < minV) minV = left->minV, minPos = left->minPos; } void gatherCnt() { minCnt = min(left->minCnt, right->minCnt); } void pushDown() { if (delay) { minCnt -= delay; if (l < r) { left->delay += delay; right->delay += delay; } delay = 0; } } void queryMin(int from, int &value, int &pos) { if (r < from) return; if (from <= l) { if (minV < value) value = minV, pos = minPos; return; } right->queryMin(from, value, pos); left->queryMin(from, value, pos); } void decSuffix(int from) { pushDown(); if (r < from) return; if (from <= l) { delay += 2; pushDown(); return; } left->decSuffix(from); right->decSuffix(from); gatherCnt(); } void erase(int i) { if (r < i || i < l) return; if (l == r) { minV = INF; return; } left->erase(i); right->erase(i); gatherMin(); } int findFirst() { pushDown(); if (minCnt > 1) return l; if (l == r) return 0; right->pushDown(); if (right->minCnt <= 1) return right->findFirst(); left->pushDown(); int ll = left->findFirst(); if (ll != 0) return ll; return right->findFirst(); } }; struct coin { int x, y, index; bool operator < (const coin &that) const { return x < that.x; } } a[N]; int n; bool was[N]; node *build(int l, int r) { node *x = new node(l, r); if (l == r) { x->minV = a[l].y; x->minPos = l; x->minCnt = l; return x; } x->left = build(l, l + r >> 1); x->right = build((l + r >> 1) + 1, r); x->gatherMin(); x->gatherCnt(); return x; } int main() { ios::sync_with_stdio(0); cin.tie(0); #ifndef ONLINE_JUDGE freopen("DIVIDE.txt", "r", stdin); #endif // ONLINE_JUDGE cin >> n; for (int i = 1; i <= n; ++i) cin >> a[i].x; for (int i = 1; i <= n; ++i) cin >> a[i].y; for (int i = 1; i <= n; ++i) a[i].index = i; sort(a + 1, a + 1 + n); long long ans = 0; for (int i = 1; i <= n; ++i) ans += a[i].y; node *root = build(1, n); for (int i = 1; i + i <= n; ++i) { int first = root->findFirst(); int minValue = INF, minPos = 0; root->queryMin(first, minValue, minPos); ans -= minValue; root->decSuffix(minPos); root->erase(minPos); was[minPos] = 1; } cout << ans << '\n'; stack<int> S; for (int i = 1; i <= n; ++i) { if (!was[i]) { S.push(a[i].index); } else { cout << S.top() << ' ' << a[i].index << '\n'; S.pop(); } } return 0; }
Comments