Cod sursa(job #585979)

Utilizator mugurelionutMugurel-Ionut Andreica mugurelionut Data 30 aprilie 2011 13:03:16
Problema Guvern Scor 60
Compilator cpp Status done
Runda Algoritmiada 2011, Runda Finală, Open Marime 4.2 kb
#include <stdio.h>
#include <string.h>
#include <vector>
#include <set>
#include <algorithm>

using namespace std;

#define NMAX 200100

set<pair<int, int> > vset;
char visited[NMAX];
int v[NMAX], o[NMAX], stk[NMAX], nidx[NMAX], parent[NMAX], sparent[NMAX], lmin[NMAX], lmax[NMAX], cmax[NMAX];
vector<int> neigh[NMAX], cbest;
vector<pair<pair<int, int>, int> > intv;
set<pair<int, int> > sbest;
int oidx, i, j, k, N, li, ls, niv, cnt, vmax, cc;

void bfs() {
    memset(visited, 0, sizeof(visited));
    memset(parent, 0, sizeof(parent));

    o[1] = 1;
    li = ls = 1;
    visited[1] = 1;

    while (li <= ls) {
        i = o[li];

        for (k = neigh[i].size() - 1; k >= 0; k--) {
            j = neigh[i][k];

            if (!visited[j]) {
                visited[j] = 1;
                ls++;
                o[ls] = j;

                parent[j] = i;
            }
        }

        li++;
    }

    // Make the neigh[i] vector contain only the sons of the node i.
    for (i = 1; i <= N; i++)
        neigh[i].clear();

    for (i = 2; i <= N; i++)
        neigh[parent[i]].push_back(i);
}

void dfs() {
    pair<int, int> p;
    set<pair<int, int> >::iterator it;

    memset(sparent, 0, sizeof(sparent));

    niv = 1;
    stk[niv] = 1;
    nidx[niv] = 0;
    vset.insert(make_pair(v[1], 1));
    lmin[1] = cnt = 1;

    while (niv > 0) {
        if (nidx[niv] == neigh[stk[niv]].size()) {
            vset.erase(make_pair(v[stk[niv]], stk[niv]));
            lmax[stk[niv]] = cnt;
            niv--;
        } else {
            i = neigh[stk[niv]][nidx[niv]];
            nidx[niv]++;

            p = make_pair(v[i], 0);
            it = vset.lower_bound(p);
            if (it != vset.end()) {
                sparent[i] = (*it).second;
            }

            niv++;
            stk[niv] = i;
            nidx[niv] = 0;
            vset.insert(make_pair(v[i], i));
            cnt++;
            lmin[i] = cnt;
        }
    }

    // Make the neigh[i] vector contain only the supersons.
    for (i = 1; i <= N; i++) {
        neigh[i].clear();
    }

    for (i = 1; i <= N; i++)
        neigh[sparent[i]].push_back(i);

    lmin[0] = 0;
    lmax[0] = N;
    o[0] = 0;
}

void compute() {
    set<pair<int, int> >::iterator it;
    pair<int, int> p;

    for (oidx = N; oidx >= 0; oidx--) {
        i = o[oidx];
        intv.clear();
        for (k = neigh[i].size() - 1; k >= 0; k--) {
            j = neigh[i][k];
            intv.push_back(make_pair(make_pair(lmax[j], lmin[j]), cmax[j]));
        }

        sort(intv.begin(), intv.end());

        // Run a DP on a set of intervals. Each interval has an associated cost. Select a subset of these intervals
        // such that no two intervals intersect and their total cost is maximum.
        if (intv.size() == 0) {
            cmax[i] = 1;
        } else {
            cbest.clear();
            sbest.clear();

            for (j = 0; j < intv.size(); j++) {
                vmax = 0;
                if (j > 0)
                    vmax = cbest[cbest.size() - 1];

                cc = intv[j].second;
                p.first = -intv[j].first.second;
                p.second = -1;
                it = sbest.upper_bound(p);

                if (it != sbest.end())
                    cc += (*it).second;

                if (cc > vmax)
                    vmax = cc;

                cbest.push_back(vmax);
                sbest.insert(make_pair(-intv[j].first.first, vmax));
            }

            cmax[i] = 1 + cbest[cbest.size() - 1];
        }
    }
}

int main() {
    // Read the input data.
    freopen("guvern.in", "r", stdin);
    scanf("%d", &N);
    for (k = 1; k < N; k++) {
        scanf("%d %d", &i, &j);
        neigh[i].push_back(j);
        neigh[j].push_back(i);
    }

    for (i = 1; i <= N; i++)
        scanf("%d", &v[i]);

    // Run a BFS on the tree in order to define the parent-son relationships.
    bfs();

    // Run a DFS on the tree.
    dfs();

    // Compute the result.
    compute();

    // Print the result.
    freopen("guvern.out", "w", stdout);
    printf("%d\n", cmax[0] - 1);

    return 0;
}