Cod sursa(job #2477260)

Utilizator NicolaalexandraNicola Alexandra Mihaela Nicolaalexandra Data 19 octombrie 2019 21:42:39
Problema Guvern Scor 10
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.82 kb
#include <fstream>
#include <vector>
#include <set>
#include <map>
#include <algorithm>
#define DIM 200010
#define INF 2000000000
using namespace std;

ifstream fin ("guvern.in");
ofstream fout ("guvern.out");
vector <int> L[DIM],g[DIM];
set <int> s;
map <int,int> f;
int t[DIM],v[DIM],dp[DIM],First[DIM],Last[DIM],E[DIM],w[DIM];
int n,i,x,y,k;
struct interval{
    int val,st,dr;
};
vector <interval> intv;
void dfs (int nod, int tata){
    E[++k] = nod;
    First[nod] = k;
    set <int> :: iterator it = s.lower_bound(v[nod]);
    if (it != s.end()){
        /// inseamna ca pe nod pot sa il leg de x
        int x = f[*it];
        g[x].push_back(nod);
        t[nod] = f[x];
    }
    s.insert (v[nod]);
    for (int i=0;i<L[nod].size();i++){
        int vecin = L[nod][i];
        if (vecin != tata)
            dfs (vecin,nod);
    }
    s.erase(s.find(v[nod]));
    Last[nod] = k;
}
inline int cmp (interval a, interval b){
    if (a.dr == b.dr)
        return a.st < b.st;
    return a.dr < b.dr;
}
void dfs2 (int nod, int tata){
    /// pot sa aleg doar dintre fiii care sunt legati direct de nod
    /// si nu am voie sa iau 2 noduri si unul sa fie stramosul altuia
    /// => pb spectacolelor pe intervalele din parcurgerea euler
    for (int i=0;i<L[nod].size();i++){
        int vecin = L[nod][i];
        if (vecin != tata)
            dfs2 (vecin,nod);
    }
    if (g[nod].size()){
        intv.clear();
        for (int i=0;i<g[nod].size();i++){
            int vecin = g[nod][i];
            intv.push_back({dp[vecin],First[vecin],Last[vecin]});
        }
        sort (intv.begin(),intv.end(),cmp);
        w[0] = intv[0].val;
        for (int i=1;i<intv.size();i++){
            /// trb sa caut cel mai din dreapta interval care se termina inainte sa inceapa intv curent
            int poz = -1;
            int st = 0, dr = i-1;
            while (st <= dr){
                int mid = (st+dr)>>1;
                if (intv[mid].dr < intv[i].st){
                    poz = mid;
                    st = mid+1;
                } else dr = mid-1;
            }
            w[i] = w[i-1];
            if (poz != -1)
                w[i] = max (w[i],w[poz]+intv[poz].val);
        }
        dp[nod] = w[intv.size()-1] + 1;
    }}
int main (){

    fin>>n;
    for (i=1;i<n;i++){
        fin>>x>>y;
        L[x].push_back(y);
        L[y].push_back(x);
    }
    int mini = INF;
    for (i=1;i<=n;i++){
        fin>>v[i];
        t[i] = -1, dp[i] = 1;
        mini = min (mini,v[i]);
    }
    if (mini < 0)
        mini *= -1;
    else mini = 0;
    for (i=1;i<=n;i++){
        v[i] += mini;
        f[v[i]] = i;
    }

    dfs (1,0);

    dfs2 (1,0);
    int sol = 0;
    for (i=1;i<=n;i++)
        sol = max (sol,dp[i]);
    fout<<sol;


    return 0;
}