Cod sursa(job #289593)

Utilizator CezarMocanCezar Mocan CezarMocan Data 26 martie 2009 20:38:42
Problema Stalpi Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.4 kb
#include <cstdio>
#include <algorithm>
#define maxn 100100
#define inf 2000000000

using namespace std;

struct stalp {
	int x, s, d, c, poz;
};

stalp v[maxn], x[maxn];
int n, i, j, val, l, r, q;
int best[maxn];
int st[4 * maxn];

bool cmp1(stalp a, stalp b) {
	if (a.x < b.x)
		return true;
	return false;
}

bool cmp2(stalp a, stalp b) {
	if (a.x + a.d < b.x + b.d)
		return true;
	return false;
}

void init() {
	for (i = 1; i <= 4 * n; i++)
		st[i] = inf;
	for (i = 1; i <= n; i++)
		best[i] = inf;
}

inline int min(int a, int b) {
	if (a < b)
		return a;
	return b;
}

inline int cauta1(int l, int r) {
	int m;
	//cautarea pentru l
	while (l <= r) {
		m = (l + r) >> 1;
		if (v[m].x < val && v[m + 1].x >= val)
			return m;
		if (v[m].x < val)
			l = m + 1;
		else
			r = m - 1;
	}
	return 0;
}

inline int cauta2(int l, int r) {
	int m;
	//cautarea pentru r
	while (l <= r) {
		m = (l + r) >> 1;
		if (v[m].x <= val && v[m + 1].x > val)
			return m;
		if (v[m].x <= val)
			l = m + 1;
		else
			r = m - 1;
	}	
	return n;
}

void query(int nod, int left, int right, int l, int r) {
	if (l == 0) {
		q = 0;
		return;
	}
	if (l <= left && right <= r) {
		if (st[nod] < q)
			q = st[nod];
		return;
	}
	int m = (left + right) >> 1;
	if (l <= m)
		query(2 * nod, left, m, l, r);
	if (r > m)
		query(2 * nod + 1, m + 1, right, l, r);
}

void update(int nod, int left, int right, int poz) {
	int m;
	while (left < right) {
		m = (left + right) >> 1;
		if (poz <= m) {
			nod = nod << 1;
			right = m;
		}
		else {
			nod = (nod << 1) + 1;
			left = m + 1;
		}
	}
	
	st[nod] = best[poz];
	nod = nod >> 1;
	
	while (nod) {
		st[nod] = min(st[nod << 1], st[(nod << 1) + 1]);
		nod = nod >> 1;
	}
}

int main() {
	freopen("stalpi.in", "r", stdin);
	freopen("stalpi.out", "w", stdout);
	
	scanf("%d", &n);
	for (i = 1; i <= n; i++) 
		scanf("%d%d%d%d", &v[i].x, &v[i].c, &v[i].s, &v[i].d);
	
	sort(v + 1, v + n + 1, cmp1);
	for (i = 1; i <= n; i++) {
		v[i].poz = i;
		x[i] = v[i];
	}
	sort(x + 1, x + n + 1, cmp2);
	init();
	
	for (i = 1; i <= n; i++) {
		val = x[i].x - x[i].s;
		l = cauta1(1, n);
		
		val = x[i].x + x[i].d;
		r = cauta2(1, n);
		
		q = inf;
		query(1, 1, n, l, n);
		
		if (q + x[i].c < best[r]) {
			best[r] = q + x[i].c;
			update(1, 1, n, r);
		}
	}
	
	printf("%d\n", best[n]);
	
	return 0;
}