제출 #530705

#제출 시각아이디문제언어결과실행 시간메모리
530705NachoLibreAliens (IOI16_aliens)C++17
100 / 100
592 ms14784 KiB
#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
#define vint vector<int>
using namespace std;
#ifndef x
// #include ".h"
#else
#endif

int n, k;
vector<ll> l, r;

ll p2(ll x) {
	return x * x;
}

ll I(int i) {
	if(r[i] < l[i + 1]) return 0;
	return p2(r[i] - l[i + 1] + 1);
}

ll P(array<ll, 3> p, ll x) {
	return p[0] * x + p[1];
}

bool CW(array<ll, 2> a, array<ll, 2> b) {
	return (a[0] * b[1] - b[0] * a[1] < 0);
}

bool CW(array<ll, 3> a, array<ll, 3> b, array<ll, 3> c) {
	a[0] = b[0] - a[0];
	a[1] = b[1] - a[1];
	b[0] = c[0] - b[0];
	b[1] = c[1] - b[1];
	return CW({a[0], a[1]}, {b[0], b[1]});
}

bool cln = 0;
bool cht = 1;
bool new_61 = 0;
bool check = 1;

array<ll, 2> dpsol(ll am) {
	vector<array<ll, 2> > dp(n);
	dp[0] = {p2(r[0] - l[0] + 1) + am, 1};
	if(cln) {
		for(int i = 1; i < n; ++i) {
			dp[i][0] = 1e18;
			for(int j = 0; j < i; ++j) {
				ll tp = dp[j][0] + p2(r[i] - l[j + 1] + 1) - I(j) + am;
				if(dp[i][0] > tp) {
					dp[i][0] = tp;
					dp[i][1] = dp[j][1] + 1;
				} else if(dp[i][0] == tp) {
					dp[i][1] = min(dp[i][1], dp[j][1] + 1);
				}
			}
			ll y = p2(r[i] - l[0] + 1) + am;
			if(dp[i][0] > y) {
				dp[i][0] = y;
				dp[i][1] = 1;
			} else if(dp[i][0] == y) {
				dp[i][1] = min(dp[i][1], 1ll);
			}
		}
		array<ll, 2> x = dp[n - 1];
		for(int i = 1; i < n; ++i) {
			dp[i][0] = 1e18;
			for(int j = 0; j < i; ++j) {
				ll tp = dp[j][0] + p2(r[i] - l[j + 1] + 1) - I(j) + am;
				if(dp[i][0] > tp) {
					dp[i][0] = tp;
					dp[i][1] = dp[j][1] + 1;
				} else if(dp[i][0] == tp) {
					dp[i][1] = max(dp[i][1], dp[j][1] + 1);
				}
			}
			ll y = p2(r[i] - l[0] + 1) + am;
			if(dp[i][0] > y) {
				dp[i][0] = y;
				dp[i][1] = 1;
			} else if(dp[i][0] == y) {
				dp[i][1] = max(dp[i][1], 1ll);
			}
		}
		array<ll, 2> y = dp[n - 1];
		if(y[1] >= k && x[1] <= k) {
			y[1] = k;
		}
		y[0] -= y[1] * am;
		return y;
	}
	deque<array<ll, 3> > d;
	int dg = 0;
	for(int i = 0; i < n; ++i) {
		// cout << i << " |\n";
		if(i > 0) {
			ll x = -r[i];
			ll c = p2(r[i] + 1) + am;
			// cout << "x, c: " << x << " " << c << endl;
			if(cht) {
				while(dg < sz(d) - 1 && P(d[dg + 1], x) < P(d[dg], x)) dg += 1;
				dp[i][0] = P(d[dg], x) + c;
				dp[i][1] = d[dg][2] + 1;
			} else {
				dp[i][0] = 1e18;
				for(int j = 0; j < sz(d); ++j) {
					ll t = P(d[j], x) + c;
					if(dp[i][0] > t) {
						dp[i][0] = t;
						dp[i][1] = d[j][2] + 1;
					} else if(dp[i][0] == t) {
						dp[i][1] = min(dp[i][1], d[j][2] + 1);
					}
				}
			}
			// cout << "a', b': " << d[dg][0] << " " << d[dg][1] << endl;
			ll y = p2(r[i] - l[0] + 1) + am;
			if(dp[i][0] >= y) {
				dp[i][0] = y;
				dp[i][1] = 1;
			}
		}
		// cout << "dp: " << dp[i][0] - 0 * dp[i][1] * am << " " << dp[i][1] << endl;
		if(i < n - 1) {
			ll a = 2ll * l[i + 1];
			ll b = dp[i][0] - I(i) - 2ll * l[i + 1];
			b += p2(l[i + 1]);
			// cout << "a, b: " << a << " " << b << endl;
			array<ll, 3> x = {a, b, dp[i][1]};
			if(cht) {
				while(sz(d) >= 2 && CW(d[sz(d) - 2], d[sz(d) - 1], x)) {
					// cout << "popped: " << d.back()[0] << " " << d.back()[1] << endl;
					d.pop_back();
				}
			}
			d.push_back(x);
			dg = min(dg, sz(d) - 1);
		}
	}
	array<ll, 2> x = dp[n - 1];
	///
	d.clear();
	dg = 0;
	dp = vector<array<ll, 2> >(n);
	dp[0] = {p2(r[0] - l[0] + 1) + am, 1};
	for(int i = 0; i < n; ++i) {
		// cout << i << " |\n";
		if(i > 0) {
			ll x = -r[i];
			ll c = p2(r[i] + 1) + am;
			// cout << "x, c: " << x << " " << c << endl;
			if(cht) {
				while(dg < sz(d) - 1 && P(d[dg + 1], x) <= P(d[dg], x)) dg += 1;
				dp[i][0] = P(d[dg], x) + c;
				dp[i][1] = d[dg][2] + 1;
			} else {
				dp[i][0] = 1e18;
				for(int j = 0; j < sz(d); ++j) {
					ll t = P(d[j], x) + c;
					if(dp[i][0] > t) {
						dp[i][0] = t;
						dp[i][1] = d[j][2] + 1;
					} else if(dp[i][0] == t) {
						dp[i][1] = min(dp[i][1], d[j][2] + 1);
					}
				}
			}
			// cout << "a', b': " << d[dg][0] << " " << d[dg][1] << endl;
			ll y = p2(r[i] - l[0] + 1) + am;
			if(dp[i][0] > y) {
				dp[i][0] = y;
				dp[i][1] = 1;
			}
		}
		// cout << "dp: " << dp[i][0] - 0 * dp[i][1] * am << " " << dp[i][1] << endl;
		if(i < n - 1) {
			ll a = 2ll * l[i + 1];
			ll b = dp[i][0] - I(i) - 2ll * l[i + 1];
			b += p2(l[i + 1]);
			// cout << "a, b: " << a << " " << b << endl;
			array<ll, 3> x = {a, b, dp[i][1]};
			if(cht) {
				while(sz(d) >= 2 && CW(d[sz(d) - 2], d[sz(d) - 1], x)) {
					// cout << "popped: " << d.back()[0] << " " << d.back()[1] << endl;
					d.pop_back();
				}
			}
			d.push_back(x);
			dg = min(dg, sz(d) - 1);
		}
	}
	array<ll, 2> y = dp[n - 1];
	if(y[1] >= k && x[1] <= k) {
		y[1] = k;
	}
	y[0] -= y[1] * am;
	return y;
}

ll dpsol_new_61() {
	vector<vector<ll> > dp(n, vector<ll>(k + 1));
	deque<array<ll, 3> > d[k + 1];
	vector<int> dg(k + 1);
	for(int i = 0; i < n; ++i) {
		dp[i][1] = p2(r[i] - l[0] + 1);
		for(int j = min(i, k - 1); j >= 0; --j) {
			// cout << "i, j + 1: " << i << " " << j + 1 << "|\n";
			if(j > 0) {
				ll x = -r[i];
				ll c = p2(r[i] + 1);
				while(dg[j] < sz(d[j]) - 1 && P(d[j][dg[j] + 1], x) < P(d[j][dg[j]], x)) dg[j] += 1;
				dp[i][j + 1] = P(d[j][dg[j]], x) + c;
			}
			// cout << "dp: " << dp[i][j + 1] << "\n";
			///////////
			if(i < n - 1) {
				ll a = 2ll * l[i + 1];
				ll b = dp[i][j + 1] - I(i) - 2ll * l[i + 1];
				b += p2(l[i + 1]);
				array<ll, 3> x = {a, b, 0};
				while(sz(d[j + 1]) >= 2 && CW(d[j + 1][sz(d[j + 1]) - 2], d[j + 1][sz(d[j + 1]) - 1], x)) {
					d[j + 1].pop_back();
				}
				d[j + 1].push_back(x);
				dg[j + 1] = min(dg[j + 1], sz(d[j + 1]) - 1);
			}
		}
	}
	return dp[n - 1][min(k, n)];
}

ll take_photos(int N, int m, int K, vint R, vint C) {
	n = N;
	k = K;
	vector<int> lg(m, m);
	for(int i = 0; i < n; ++i) {
		array<int, 2> x = {R[i], C[i]};
		if(x[0] > x[1]) swap(x[0], x[1]);
		lg[x[1]] = min(lg[x[1]], x[0]);
	}
	vector<array<int, 2> > v;
	for(int i = 0; i < m; ++i) {
		if(lg[i] == m) continue;
		while(sz(v) && lg[i] <= v.back()[0]) {
			v.pop_back();
		}
		v.push_back({lg[i], i});
	}
	n = sz(v);
	l = r = vector<ll>(n);
	for(int i = 0; i < n; ++i) {
		l[i] = v[i][0];
		r[i] = v[i][1];
	}
	///
	if(new_61) {
		return dpsol_new_61();
	}
	///
	ll al = 0, ar = 1ll * m * m;
	// al = ar = 4;
	while(al < ar) {
		ll am = (al + ar) / 2;
		if(dpsol(am)[1] > k) al = am + 1;
		else ar = am;
	}
	array<ll, 2> x = dpsol(al);
	// cout << x[1] << " " << al << endl;
	if(al && x[1] < k && dpsol(al - 1)[1] > k && check) {
		cout << "\n[alien brick]: {\n";
		cout << "al: " << al << "\n";
		cout << al << " cnt: " << x[1] << "\n";
		cout << al - 1 << " cnt: " << dpsol(al - 1)[1] << "\n";
		cout << "k: " << k << "\n}\n" << endl;
		// assert(0);
	}
	// cout << "[]: " << al << " " << k << " " << dpsol(al)[1] << endl;
	return x[0];
}

#ifdef x
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout << take_photos(4, 4, 2, {0, 1, 2, 3}, {0, 1, 2, 3}) << endl;
	// return 0;
	cout << "----" << endl;
	cout << take_photos(9, 9, 2, {0, 1, 2, 3, 4, 5, 6, 7, 8}, {0, 1, 2, 3, 4, 5, 6, 7, 8}) << endl;
	cout << "----" << endl;
	cout << take_photos(5, 5, 5, {0, 1, 2, 3, 4}, {0, 1, 2, 3, 4}) << endl;
	cout << take_photos(5, 5, 4, {0, 1, 2, 3, 4}, {0, 1, 2, 3, 4}) << endl;
	cout << take_photos(5, 5, 3, {0, 1, 2, 3, 4}, {0, 1, 2, 3, 4}) << endl;
	cout << take_photos(5, 5, 2, {0, 1, 2, 3, 4}, {0, 1, 2, 3, 4}) << endl;
	cout << take_photos(5, 5, 1, {0, 1, 2, 3, 4}, {0, 1, 2, 3, 4}) << endl;
	cout << "----" << endl;
	cout << take_photos(2, 2, 1, {0, 1}, {0, 1}) << endl;
	cout << take_photos(2, 2, 2, {0, 1}, {0, 1}) << endl;
	cout << take_photos(1, 2, 1, {0}, {1}) << endl;
	cout << "----" << endl;
	cout << take_photos(5, 7, 1, {0, 4, 4, 4, 4}, {3, 4, 6, 5, 6}) << endl;
	cout << take_photos(5, 7, 2, {0, 4, 4, 4, 4}, {3, 4, 6, 5, 6}) << endl;
	cout << take_photos(2, 6, 2, {1, 4}, {4, 1}) << endl;
	return 0;
}
#endif
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...