Cod sursa(job #137609)

Utilizator alextheroTandrau Alexandru alexthero Data 17 februarie 2008 12:47:51
Problema Stalpi Scor 100
Compilator cpp Status done
Runda preONI 2008, Runda 4, Clasa a 10-a Marime 2.41 kb
#include <stdio.h>
#include <algorithm>
#include <vector>

#define min(i,j) ((i) > (j) ? (j) : (i))
#define nmax 100005
#define arbmax 400005

using namespace std;
typedef pair<int, int> ii;
typedef pair<ii, int> iii;
typedef pair<ii, ii> iiii;

int n, nx, ny, l, r, first, last, caut;
long long c[nmax], minim;
long long arb[arbmax], inf;
iiii a[nmax];
vector <iii> v;

long long query(int nod, int first, int last, int s1, int s2)
{
	if(s1 <= first && last <= s2) return arb[nod];
	else
	{
		int mid = (first + last ) / 2;
		long long rez = inf;
		if(s1 <= mid) rez = min(rez, query(nod * 2, first, mid, s1, s2));
		if(s2 > mid) rez = min(rez, query(nod * 2 + 1, mid + 1, last, s1, s2));
		return rez;
	}
}

void update(int nod, int first, int last, int s1)
{
	if(first == last) arb[nod] = c[first];
	else
	{
		int mid = (first + last) / 2;
		if(s1 <= mid) update(nod * 2, first, mid, s1);
		else update(nod * 2 + 1, mid + 1, last, s1);
		arb[nod] = min(arb[nod * 2], arb[nod * 2 + 1]);
	}
}

void init(int nod, int first, int last)
{
	if(first == last) arb[nod] = c[first];
	else
	{
		int mid = (first + last) / 2;
		init(nod * 2, first, mid);
		init(nod * 2 + 1, mid + 1, last);
		arb[nod] = min(arb[nod * 2], arb[nod * 2 + 1]);
	}
}

int main()
{
	freopen("stalpi.in", "r", stdin);
	freopen("stalpi.out", "w", stdout);

	scanf("%d", &n);
	for(int i = 1; i <= n; i++) scanf("%d%d%d%d", &a[i].first.first, &a[i].first.second, &a[i].second.first, &a[i].second.second);

	sort(a + 1, a + n + 1);

	for(int i = 1; i <= n; i++)
	{
		nx = 1, first = 1, last = n, caut = a[i].first.first - a[i].second.first;
		while(first <= last)
		{
			int mid = (first + last) / 2;
			if(a[mid].first.first >= caut) nx = mid, last = mid - 1;
			else first = mid + 1;
		}

		ny = n, first = 1, last = n, caut = a[i].first.first + a[i].second.second;
		while(first <= last)
		{
			int mid = (first + last) / 2;
			if(a[mid].first.first <= caut) ny = mid, first = mid + 1;
			else last = mid - 1;
		}

		v.push_back(iii(ii(nx + 1, ny + 1), a[i].first.second));
	}
	sort(v.begin(), v.end()); 

	inf = 1 << 20; inf *= inf;
	for(int i = 0; i <= n + 2; i++) c[i] = inf;

	init(1, 1, n + 1);
	c[1] = 0;
	update(1, 1, n + 1, 1);
	for(int i = 0; i < (int)v.size(); i++)
	{
		minim = query(1, 1, n + 1, v[i].first.first - 1, n + 1);
		c[v[i].first.second] = min(c[v[i].first.second], minim + v[i].second);
		update(1, 1, n + 1, v[i].first.second);
	}
	printf("%Ld\n", c[n + 1]);

	return 0;
}