Cod sursa(job #137397)

Utilizator MariusMarius Stroe Marius Data 17 februarie 2008 11:56:51
Problema Stalpi Scor 10
Compilator cpp Status done
Runda preONI 2008, Runda 4, Clasa a 10-a Marime 2.55 kb
#include <cstdio>

#include <set>
#include <algorithm>

using namespace std;

const char iname[] = "stalpi.in";
const char oname[] = "stalpi.out";

#define MAXN  100005
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define FOR(i, a, b) for (int i = (a); i <= (b); ++ i)
#define left(n)   (n << 1)
#define right(n) ((n << 1) + 1)

typedef long long i64;

const i64 inf = (i64)(1e13);

struct entry {
	int x, c, s, d;
} A[MAXN];

int n;

int Xc[MAXN];

set <pair <int, int> > Q;

multiset <i64> V;

i64 C[MAXN], S[MAXN];

i64 T[262144];


void read_in(void)
{
	FILE *fi;
	
	fi = fopen(iname, "r");

	fscanf(fi, "%d", &n);
	FOR(i, 1, n)
		fscanf(fi, "%d %d %d %d", &A[i].x, &A[i].c, &A[i].s, &A[i].d);

	fclose(fi);
}

void _update(int n, int lo, int hi)
{
	int mid = (hi + lo) >> 1;

	if (hi == lo)
		T[n] = C[hi];
	else {
		_update(left(n), lo, mid);
		_update(right(n), mid + 1, hi);
		T[n] = Min(T[left(n)], T[right(n)]);
	}
}

void update(int n, int lo, int hi, int pos)
{
	int mid = (hi + lo) >> 1;

	if (hi == lo)
		T[n] = C[hi];
	else {
		if (pos <= mid)
			update(left(n), lo, mid, pos);
		else
			update(right(n), mid + 1, hi, pos);
		T[n] = Min(T[left(n)], T[right(n)]);
	}
}

i64 query(int n, int lo, int hi, int a, int b)
{
	int mid = (hi + lo) >> 1;
	i64 l = inf;
	i64 r = inf;

	if (a <= lo && hi <= b)
		return T[n];
	if (a <= mid)
		l = query(left(n), lo, mid, a, b);
	if (b > mid)
		r = query(right(n), mid + 1, hi, a, b);

	return Min(l, r);
}

bool mycmp(entry a, entry b) {
	return a.x < b.x;
}

int main(void)
{
	FILE *fo;

	read_in();

	fo = fopen(oname, "w");

	sort(A+1, A+1 + n, mycmp);

	FOR(i, 1, n) 
	{
		Xc[i] = A[i].x;
		C[i] = S[i] = inf;
	}

	C[1] = A[1].c;
	Q.insert(pair <int, int>(A[1].x + A[1].d, 1));
	V.insert(C[1]);

	_update(1, 1, n);

	FOR(i, 2, n)
	{
		// calculam pentru becul aprins
		int j = (int)(lower_bound(Xc, Xc + i, A[i].x - A[i].s) - Xc);
		i64 cmin = inf, tmp = inf;
		
		if (j > 0) {
			if (Xc[j] < A[i].x - A[i].s)
				cmin = S[j];
			else
				j --, cmin = S[j];
		} else
			cmin = 0;

		if (j + 1 <= i - 1)
			tmp = query(1, 1, n, j+1, i-1);
		cmin = Min(cmin, tmp);

		C[i] = cmin + A[i].c;

		update(1, 1, n, i);

		// calculam pentru becul stins
		while (!Q.empty())
		{
			if ((*Q.begin()).first < A[i].x)
			{
				V.erase(V.find(C[(*Q.begin()).second]));
			
				Q.erase(Q.begin());
			}
			else
				break ;
		}
		if (V.size() > 0)
			S[i] = *V.begin();
		else
			S[i] = inf;

		Q.insert(pair <int, int>(A[i].x + A[i].d, i));

		V.insert(C[i]);
	}

	fprintf(fo, "%lld\n", Min(C[n], S[n]));

	fclose(fo);

	return 0;
}