제출 #1346098

#제출 시각아이디문제언어결과실행 시간메모리
1346098vlomaczkPotatoes and fertilizers (LMIO19_bulves)C++20
100 / 100
1000 ms74804 KiB
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
typedef long long ll;
using namespace __gnu_pbds;
using namespace std;

template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

template <typename TY>
struct MultiOrderedSet {
	ordered_set<pair<TY, ll>> os;
	ll cnt = 0;
	void insert(TY x) {
		os.insert({x, cnt++});
	}
	void erase(TY x) {
		ll idx = os.order_of_key({x,-1});
		assert(idx < (ll)os.size());
		os.erase(*os.find_by_order(idx));
	}
	TY first() { return os.begin()->first; }
	TY last() { return os.rbegin()->first; }
	void clear() {
		while(os.size()) os.erase(*os.begin());
	}
	ll size() { return os.size(); }
	bool empty() { return os.empty(); }
	ll order_of_key(TY x) {
		return os.order_of_key({x, -1});
	}
	TY find_by_order(ll x) {
		return os.find_by_order(x)->first;
	}
};

struct SlopeTrick {
	ll A=0, B=0;
	ll Xoffset = 0;
	MultiOrderedSet<ll> ms;

	void append(SlopeTrick s) {
		for(auto[x,a] : s.ms.os) {
			x += s.Xoffset;
			ms.insert(x - Xoffset);
		}
		A += s.A;
		B += s.B;
	}

	void shift(ll x) { // f'(x) = f(x - a)
		Xoffset += x;
		B -= x*A;
	}

	void drop_slope() {
		ll X = ms.last();
		ms.erase(X);
		X+=Xoffset;
		A--;
		B += X;
	}

	ll query(ll x) {
		while(ms.size() && ms.last() + Xoffset > x) drop_slope();
		return A * x + B;
	}

	void cut_back() {
		while((ll)ms.size() > A) ms.erase(ms.first());
	}
	
	void cut_front() {
		while(A > 0) drop_slope();
	}

	void writeout() {
		cout << "(" << A << " " << B << "): ";
		for(auto x : ms.os) cout << x.first+Xoffset << " ";
		cout << "\n";
	}
};

int main() {
	ios_base::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);

	ll n;
	cin >> n;
	vector<ll> P(n), F(n);
	for(ll i=0; i<n; ++i) cin >> F[i] >> P[i];
	vector<ll> prefix(n);
	prefix[0] = F[0] - P[0];
	for(ll i=1; i<n; ++i) prefix[i] = prefix[i-1] + F[i] - P[i];

	SlopeTrick res;

	if(F[0] - P[0] < 0) {
		ll x = F[0] - P[0];
		ll slope = n+5;
		for(ll i=0; i<slope; ++i) res.ms.insert(x);
		res.A = slope-1;
		res.B = -x + res.A*(-x);
	} else {
		ll x = F[0] - P[0];
		res.ms.insert(0);
		res.ms.insert(0);
		ll slope = n+5;
		for(ll i=0; i<slope; ++i) res.ms.insert(x);\
		res.A = slope+1;
		res.B = x*(-slope);
	}

	for(ll i=1; i<n; ++i) {
		res.shift(-(P[i] - F[i]));
		
		res.cut_back();

		SlopeTrick dodaj;
		dodaj.ms.insert(0); dodaj.ms.insert(0); dodaj.A=1; // f(x) = |x|

		res.append(dodaj);
	}
	cout << res.query(0) << "\n";

	return 0;
}
#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...