Cod sursa(job #994402)

Utilizator vendettaSalajan Razvan vendetta Data 5 septembrie 2013 14:48:36
Problema Stalpi Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.84 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <set>
#include <queue>
#include <deque>

using namespace std;

ifstream f("stalpi.in");
ofstream g("stalpi.out");

#define ll long long
#define pb push_back
#define mp make_pair
#define sz size
#define x first
#define y second

#define nmax 100005
#define inf (1<<29)
#define X first.first
#define C first.second
#define S second.first
#define D second.second

int n, dp[nmax];
pair< pair<int,int>, pair<int,int> > v[nmax];
vector< pair<int,int> > lista[nmax];
int aint[nmax*3];

void citeste(){
    f >> n;
    for(int i=1; i<=n; ++i){
        int x, c, s, d;
        f >> x >> c >> s >> d;
        v[i] = ( mp( mp(x, c), mp(s, d) ) );
    }
}

inline int cbSt(int Val){
    int st = 0; int dr = n+1;
    while(dr - st > 1){
        int mij = (st + dr) >> 1;
        if (v[mij].X < Val){// pe asta nu il mai poate acoperi
            st = mij;
        }else dr = mij;
    }
    return st;
}

inline int cbDr(int Val){
    int st = 0; int dr = n+1;
    while(dr - st > 1){
        int mij = (st + dr) >> 1;
        if (v[mij].X > Val){
            dr = mij;
        }else st = mij;
    }
    return dr - 1;
}

void update(int nod, int st, int dr, int poz, int val){
    if (st == dr){
        aint[nod] = val;
        return;
    }else{
        int mij = (st + dr) >> 1;
        if (poz <= mij) update(nod*2, st, mij, poz, val);
                   else update(nod*2+1, mij+1, dr, poz, val);
        aint[nod] = min(aint[nod*2], aint[nod*2+1]);
    }
}

void query(int nod, int st, int dr, int a, int b, int &Min){
    if (a <= st && dr <= b){
        Min = min(Min, aint[nod]);
        return;
    }else{
        int mij = (st + dr) >> 1;
        if (a <= mij) query(nod*2, st, mij, a, b, Min);
        if (b > mij) query(nod*2+1, mij+1, dr, a, b, Min);
    }
}

void rezolva(){
    // transform fiecare stalp intr-un intertval ca sa il pot trata de la dreapta la stanga si atunci o sa vina
    // dp[i] = costul minim a. i. sa acopar primii i stalpi iar ultimul interval sa se termine pe i;
    sort(v+1, v+n+1);
    for(int i=1; i<=n; ++i){
        int St = cbSt(v[i].X-v[i].S);// am nevoie de primul din stanga mea pe care nu il acopar
        int Dr = cbDr(v[i].X+v[i].D);
        lista[Dr].pb( mp( St, v[i].C ) );
    }

    for(int i=1; i<=n*3; ++i) aint[i] = inf;
    update(1, 0, n, 0, 0);

    for(int i=1; i<=n; ++i){
        dp[i] = inf;
        int Min = inf;
        for(int j=0; j<lista[i].sz(); ++j){
            int Min2 = inf;
            query(1, 0, n, lista[i][j].x, i-1, Min2);
            Min = min(Min, Min2 + lista[i][j].y);
        }
        update(1, 0, n, i, Min);
        dp[i] = Min;
    }
    g << dp[n] << "\n";
}

int main(){
    citeste();
    rezolva();

    f.close();
    g.close();

    return 0;
}