Cod sursa(job #178575)

Utilizator moga_florianFlorian MOGA moga_florian Data 14 aprilie 2008 19:32:49
Problema Stalpi Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.97 kb
#include<stdio.h>
#define Nmax 100010

int N;
int X[Nmax];
struct nod{int s,d,c;} A[Nmax];

long long arb[3*Nmax];
char ult[3*Nmax];
long long inf = (long long)1000000 * (long long)100000;
long long MIN;
int POS;


void insert(int i,int li,int lf, int st, int dr, long long val){

	if(lf < st || dr < li)
	    return;

	if(st <= li && lf <= dr){
		arb[i] = val;
		ult[i] = 1;
		return;
	}

	int mij = (li+lf) / 2;
	if(ult[i]){
		arb[2*i] = arb[2*i+1] = arb[i];
		ult[2*i] = ult[2*i+1] = 1;
		ult[i] = 0;
	}

	insert(2*i,li,mij,st,dr,val);
	insert(2*i+1,mij+1,lf,st,dr,val);

	arb[i] = arb[2*i];
	if(arb[2*i+1] < arb[i])
	    arb[i] = arb[2*i+1];

}

void find_min(int i,int li, int lf, int st, int dr){

	if(lf < st || dr < li)
	    return;

	if(st <= li && lf <= dr){
		if(arb[i] < MIN)
		    MIN = arb[i];
		return;
	}

	int mij = (li+lf)>>1;
	if(ult[i]){
		if(arb[i] < MIN)
		    MIN = arb[i];
		return;
	}

    find_min(2*i,li,mij,st,dr);
    find_min(2*i+1,mij+1,lf,st,dr);

}

void find_pos(int i, int li, int lf, long long goal){

    if(POS < li) return;

	if(arb[i] >= goal){
		if(li < POS)
		    POS = li;
		return;
	}

	if(ult[i])
	    return;

	int mij = (li+lf)>>1;

	if(arb[2*i] == arb[2*i+1])
	    find_pos(2*i+1,mij+1,lf,goal);
	else{

		if(arb[2*i+1] >= goal){
			if(POS > mij+1)
			    POS = mij+1;
			find_pos(2*i,li,mij,goal);
		}
		else
		    find_pos(2*i+1,mij+1,lf,goal);

	}

}

int main(){

	FILE *fin = fopen("stalpi.in","r"),
		 *fout = fopen("stalpi.out","w");

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

	for(int i=1;i<=N;i++)
	    fscanf(fin,"%d%d%d%d",&X[i],&A[i].c,&A[i].s,&A[i].d);

	for(int i=1;i<=N;i++)
	    A[i].s = X[i] - A[i].s, A[i].d = X[i] + A[i].d;

	//sort A
	for(int i=1;i<=N;i++){
		int j = i;
		while(j/2 && A[j].d > A[j/2].d){
			nod aux = A[j];
			A[j] = A[j/2];
			A[j/2] = aux;
			j>>=1;
		}
	}

	int cate = N;
	while(cate > 1){
		nod aux = A[1];
		A[1] = A[cate];
		A[cate] = aux;
		cate --;

		int j = 1;
		while(1){
			int k = j<<1;
			if(k>cate) break;
			if(k+1 <= cate && A[k+1].d > A[k].d) k++;
			if(A[j].d >= A[k].d) break;

			aux = A[j];
			A[j] = A[k];
			A[k] = aux;

			j = k;
		}
	}

	//sort X
	for(int i=1;i<=N;i++){
		int j = i;
		while(j/2 && X[j/2] < X[j]){
			int aux = X[j/2];
			X[j/2] = X[j];
			X[j] = aux;
			j>>=1;
		}
	}

	cate = N;
	while(cate > 1){
		int aux = X[1];
		X[1] = X[cate];
		X[cate] = aux;
		cate --;

		int j = 1;
		while(1){
			int k = j*2;
			if(k>cate) break;
			if(k+1 <= cate && X[k+1] > X[k]) k++;
			if(X[j] >= X[k]) break;

			aux = X[j];
			X[j] = X[k];
			X[k] = aux;
			j = k;
		}
	}

	/*
	//test
	for(int i=1;i<=N;i++)
	    fprintf(fout,"%d\n",X[i]);

	for(int i=1;i<=N;i++)
	    fprintf(fout,"%d %d\n",A[i].s,A[i].d);
	*/

	arb[1] = inf;
	ult[1] = 1;

	for(int i=1;i<=N;i++){
		//intervalul A[i].s - A[i].d
		//aflare L si R

		int L=-1,R=N+1;
		int li,lf,mij;

		li = 1;lf = N;
		while(li<=lf){
			mij = (li+lf) / 2;
			if(X[mij] < A[i].s){
				L = mij;
				li = mij + 1;
			}
			else
				lf = mij - 1;
		}

		//if(L < 0) L = 1;

		li = 1;lf = N;
		while(li<=lf){
			mij = (li+lf)/2;
			if(X[mij] <= A[i].d){
				R = mij;
				li = mij+1;
			}
			else
			    lf = mij-1;
		}
		//if(R > N) R = N;

		/*
		//test2
		fprintf(fout,"%d %d\n",L,R);
		*/

		//procesare
		if(L<0)
			MIN = 0;
		else{
			MIN = inf;
			find_min(1,1,N,L,N);
		}

		MIN += (long long)A[i].c;

		POS = N+1;
		find_pos(1,1,N,MIN);

		if(POS > R);
		else
            insert(1,1,N,POS,R,MIN);
/*
        for(int k=1;k<=N;k++){
            MIN = inf;
            find_min(1,1,N,k,k);
            if(MIN == inf)
                break;
            else
                fprintf(fout,"%lld ",MIN);
        }
        fprintf(fout,"\n");
*/

	}

    MIN = inf;
    find_min(1,1,N,N,N);

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

	fclose(fin);
	fclose(fout);
	return 0;

}