Submission #681412

#TimeUsernameProblemLanguageResultExecution timeMemory
681412GusterGoose27Potatoes and fertilizers (LMIO19_bulves)C++11
100 / 100
487 ms144052 KiB
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

#define int long long

const int MAXN = 5e5;
const ll inf = 1e18;
int n;
int vals[MAXN];
ll pre[MAXN];
int ben[MAXN];

class stree {
public:
	int lp, rp;
	stree *l = nullptr;
	stree *r = nullptr;
	pii mx;
	int lz = 0;
	stree(int lv, int rv) {
		lp = lv;
		rp = rv;
		if (lp < rp) {
			int m = (lp+rp)/2;
			l = new stree(lp, m);
			r = new stree(m+1, rp);
			mx = max(l->mx, r->mx);
		}
		else {
			mx = pii(ben[lp], lp);
		}
	}
	void add_to(int v) {
		lz += v;
		mx.first += v;
	}
	void push() {
		if (l) {
			l->add_to(lz);
			r->add_to(lz);
		}
		lz = 0;
	}
	void upd(int lv, int rv, int v) {
		if (lp > rv || rp < lv) return;
		if (lp >= lv && rp <= rv) {
			return add_to(v);
		}
		push();
		l->upd(lv, rv, v);
		r->upd(lv, rv, v);
		mx = max(l->mx, r->mx);
	}
	pii get_mx(int lv, int rv) {
		if (lp > rv || rp < lv) return pii(-1, -1);
		if (lp >= lv && rp <= rv) return mx;
		push();
		return max(l->get_mx(lv, rv), r->get_mx(lv, rv));
	}
};

stree *mx_tree;

class stree2 {
public:
	int lp, rp;
	stree2 *l = nullptr;
	stree2 *r = nullptr;
	ll mn;
	ll sub = 0;
	stree2(int lv, int rv) {
		lp = lv;
		rp = rv;
		if (lp < rp) {
			int m = (lp+rp)/2;
			l = new stree2(lp, m);
			r = new stree2(m+1, rp);
			mn = min(l->mn, r->mn);
		}
		else {
			if (pre[lp] <= 0) mn = inf;
			else mn = pre[lp];
		}
	}
	void erase() {
		if (mn) return;
		if (lp == rp) {
			mn = inf;
			mx_tree->upd(0, lp, -2);
			return;
		}
		push();
		l->erase();
		r->erase();
		mn = min(l->mn, r->mn);
	}
	void add_to(int v) {
		mn += v;
		sub += v;
		if (mn == 0) {
			erase();
		}
	}
	void push() {
		if (l) {
			l->add_to(sub);
			r->add_to(sub);
		}
		sub = 0;
	}
	void upd(int lv, int rv, int v) {
		if (lp > rv || rp < lv) return;
		if (lp >= lv && rp <= rv) {
			add_to(v);
			return;
		}
		push();
		l->upd(lv, rv, v);
		r->upd(lv, rv, v);
		mn = min(l->mn, r->mn);
	}
	ll query(int lv, int rv) {
		if (lp > rv || rp < lv) return inf;
		if (lp >= lv && rp <= rv) return mn;
		push();
		return min(l->query(lv, rv), r->query(lv, rv));
	}
};

stree2 *beat_tree;

signed main() {
	ios_base::sync_with_stdio(false); cin.tie(NULL);
	cin >> n;
	ll ans = 0;
	for (int i = 0; i < n; i++) {
		int x, y; cin >> x >> y;
		vals[i] = x-y;
		pre[i] += vals[i];
		if (i < n-1) pre[i+1] = pre[i];
		ans += (pre[i] < 0) ? (-pre[i]) : pre[i];
	}
	for (int i = n-1; i >= 0; i--) {
		if (pre[i] <= 0) ben[i]--;
		else ben[i]++;
		if (i) ben[i-1] = ben[i];
	}
	mx_tree = new stree(0, n-1);
	beat_tree = new stree2(0, n-1);
	pii bst = mx_tree->get_mx(0, n-1);
	ll rem = pre[n-1];
	while (bst.first && rem) {
		ll lim = beat_tree->query(bst.second, n-1);
		lim = min(lim, rem);
		ans -= lim*bst.first;
		beat_tree->upd(bst.second, n-1, -lim);
		bst = mx_tree->get_mx(0, n-1);
		rem -= lim;
	}
	cout << ans << "\n";
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...