Cod sursa(job #125481)

Utilizator ProstuStefan-Alexandru Filip Prostu Data 20 ianuarie 2008 12:59:26
Problema Inundatii Scor 0
Compilator cpp Status done
Runda preONI 2008, Runda 3, Clasa a 10-a Marime 2.25 kb
#include <cstdio>
#include <algorithm>

using namespace std;

typedef long long llong;
typedef pair <llong, int> PLI;

#define x first
#define y second

const int NMAX = 1 << 16;
const int INF = 0x3f3f3f3f;
const int MIN = -NMAX, MAX = INF;

int N;
int A[NMAX], B[NMAX], C[NMAX];
int O[NMAX], NO;
PLI SM[NMAX], Sm[NMAX];

void read(void) {
	FILE *fin = fopen("inundatii.in", "rt");
	int i;

	fscanf(fin, " %d", &N);

	for (i = 1; i <= N; ++i)
		fscanf(fin, " %d %d %d", A+i, B+i, C+i);

	fclose(fin);
}

void update(PLI S[], int poz, int x, int y) {
	for (;poz <= NO+1; poz += poz & ~(poz-1))
		S[poz].x += x,
		S[poz].y += y;
}

PLI query(PLI S[], int poz) {
	PLI rez;
	rez.x = rez.y = 0;
	for (; poz > 0; poz -= poz & ~(poz-1))
		rez.x += S[poz].x,
		rez.y += S[poz].y;
	return rez;
}

llong get(int p, int h) {
	int i;
	PLI ans, aux;
	llong rez;

	i = lower_bound(O, O + NO, h) - O + 1;
	ans = query(Sm, i);
	rez = ans.x - (llong)(h - MIN) * ans.y;

	i = upper_bound(O, O + NO, h) - O + 1;
	ans = query(SM, NO);
	aux = query(SM, i-1);
	ans.x -= aux.x; ans.y -= aux.y;
	rez += ans.x - (llong)(INF - N - p - h) * ans.y;

	return rez;
}

int seek(int p, int l, int h) {
	if (l == h) return l;
	if (h - l <= 3) {
		int i, poz = l, t, aux;
		t = get(p, l);
		for (i = l+1; i <= h; ++i)
			if ((aux = get(p, i)) < t)
				t = aux, poz = i;
		return poz;
	}

	int l3, h3;
	l3 = (l * 2 + h) / 3;
	h3 = (l + 2 * h) / 3;
	if (get(p, l3) < get(p, h3))
		return seek(p, l3, h);
	else
		return seek(p, l, h3);
}

llong solve(int A[]) {
	int i, j, lh, h;
	llong rez = 0;

	for (i = 1; i <= N; ++i)
		O[i] = A[i];
	O[0] = INF;
	sort(O, O + NO+1);
	NO = unique(O, O + NO+1) - O;

	for (i = 1; i <= N; ++i) {
		j = lower_bound(O, O + NO, A[i]) - O + 1;
		update(SM, j, MAX - (N - i) - A[i], 1);
		update(Sm, j, A[i] - MIN + i, 1);
	}
	printf("ok\n");

	lh = MIN;
	for (i = 1; i <= N; ++i) {
		h = seek(i, lh, INF);
		rez = abs(h - A[i]);
		lh = h + 1;
		j = lower_bound(O, O + NO, A[i]) - O + 1;
		update(SM, j, -(MAX - (N - i) - A[i]), -1);
		update(Sm, j, -(A[i] - MIN + i), -1);
	}
	return rez;
}

void write(void) {
	FILE *fout = fopen("inundatii.out", "wt");

	llong rez;
	
	rez = solve(A) + solve(B) + solve(C);

	fprintf(fout, "%lld\n", rez);

	fclose(fout);
}

int main(void) {

	read();

	write();

	return 0;
}