제출 #405713

#제출 시각아이디문제언어결과실행 시간메모리
405713rainboyAliens (IOI16_aliens)C11
100 / 100
181 ms6588 KiB
#include "aliens_c.h"

#define N	100000
#define INF	0x3f3f3f3f3f3f3f3f

unsigned int X = 12345;

int rand_() {
	return (X *= 3) >> 1;
}

int aa[N], bb[N];

void sort(int *ii, int l, int r) {
	while (l < r) {
		int i = l, j = l, k = r, i_ = ii[l + rand_() % (r - l)], tmp;

		while (j < k) {
			int c = aa[ii[j]] != aa[i_] ? aa[ii[j]] - aa[i_] : bb[i_] - bb[ii[j]];

			if (c == 0)
				j++;
			else if (c < 0) {
				tmp = ii[i], ii[i] = ii[j], ii[j] = tmp;
				i++, j++;
			} else {
				k--;
				tmp = ii[j], ii[j] = ii[k], ii[k] = tmp;
			}
		}
		sort(ii, l, i);
		l = k;
	}
}

long long dp[N + 1], xx[N + 1], yy[N + 1]; int kk[N + 1];

long long cross(int i, int j, int k) {
	return (xx[j] - xx[i]) * (yy[k] - yy[i]) - (xx[k] - xx[i]) * (yy[j] - yy[i]);
}

long long dot(long long x1, long long y1, long long x2, long long y2) {
	return x1 * x2 + y1 * y2;
}

long long eval(int i, long long x) {
	return xx[i] * x - yy[i];
}

void solve(int *ii, int n, long long c) {
	static int qu[N + 1];
	int i, head, cnt;

	dp[0] = 0, kk[0] = 0;
	xx[0] = aa[ii[0]], yy[0] = dp[0] + (long long) aa[ii[0]] * aa[ii[0]];
	head = cnt = 0;
	qu[head + cnt++] = 0;
	for (i = 1; i <= n; i++) {
		int b = bb[ii[i - 1]];

		while (cnt >= 2 && eval(qu[head], b * 2) < eval(qu[head + 1], b * 2))
			head++, cnt--;
		dp[i] = -eval(qu[head], b * 2) + (long long) b * b + c, kk[i] = kk[qu[head]] + 1;
		if (i < n) {
			int a = aa[ii[i]];

			if (b > a)
				dp[i] -= (long long) (b - a) * (b - a);
			xx[i] = a, yy[i] = dp[i] + (long long) a * a;
			while (cnt >= 2 && cross(qu[head + cnt - 2], qu[head + cnt - 1], i) <= 0)
				cnt--;
			qu[head + cnt++] = i;
		}
	}
}

long long take_photos(int n, int m, int k, int *rr, int *cc) {
	static int ii[N];
	int n_, i;
	long long lower, upper;

	for (i = 0; i < n; i++) {
		int tmp;

		aa[i] = rr[i], bb[i] = cc[i];
		if (aa[i] > bb[i])
			tmp = aa[i], aa[i] = bb[i], bb[i] = tmp;
		bb[i]++;
		ii[i] = i;
	}
	sort(ii, 0, n);
	n_ = 0;
	for (i = 0; i < n; i++)
		if (n_ == 0 || bb[ii[n_ - 1]] < bb[ii[i]])
			ii[n_++] = ii[i];
	n = n_;
	lower = -1, upper = (long long) m * m + 1;
	while (upper - lower > 1) {
		long long c = (lower + upper) / 2;

		solve(ii, n, c);
		if (kk[n] <= k)
			upper = c;
		else
			lower = c;
	}
	solve(ii, n, upper);
	return dp[n] - upper * k;
}
#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...