Cod sursa(job #1367171)

Utilizator AlexandruValeanuAlexandru Valeanu AlexandruValeanu Data 1 martie 2015 17:39:08
Problema Heavy Path Decomposition Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 4.08 kb
#include <bits/stdc++.h>

using namespace std;

const int Nmax = 100000 + 1;

int Merge(int a, int b)
{
    return max(a, b);
}

class SegmentTree
{
public:

    SegmentTree (const vector<int>& v)
    {
        N = static_cast<int>( v.size() );
        A = vector<int>(4 * N, 0);

        build(1, 0, N - 1, v);
    }

    void update(int pos, int new_val)
    {
        update(1, 0, N - 1, pos, new_val);
    }

    int query(int x, int y)
    {
        return query(1, 0, N - 1, x, y);
    }

    void build(int nod, int st, int dr, const vector<int>& v)
    {
        if (st == dr)
            A[nod] = v[st];
        else
        {
            int m = (st + dr) / 2;

            build(2 * nod, st, m, v);
            build(2 * nod + 1, m + 1, dr, v);

            A[nod] = Merge(A[2 * nod], A[2 * nod + 1]);
        }
    }

    void update(int nod, int st, int dr, int pos, int value)
    {
        if (st == dr)
            A[nod] = value;
        else
        {
            int m = (st + dr) / 2;

            if ( pos <= m )
                update(2 * nod, st, m, pos, value);
            else
                update(2 * nod + 1, m + 1, dr, pos, value);

            A[nod] = Merge(A[2 * nod], A[2 * nod + 1]);
        }
    }

    int query(int nod, int st, int dr, int st_q, int dr_q)
    {
        if (st_q <= st && dr <= dr_q)
            return A[nod];
        else
        {
            int m = (st + dr) / 2;
            int sol = numeric_limits<int>::min();

            if ( st_q <= m )
                sol = Merge(sol, query(2 * nod, st, m, st_q, dr_q));

            if ( m < dr_q )
                sol = Merge(sol, query(2 * nod + 1, m + 1, dr, st_q, dr_q));

            return sol;
        }
    }

private:

    int N;
    vector<int> A;
};

vector<SegmentTree> ST;
vector<int> G[Nmax];
int father[Nmax], size[Nmax], depth[Nmax], value[Nmax], path[Nmax];
int pos_in_path[Nmax], length_path[Nmax], start_node[Nmax];

int N, Q, NrPaths;

void dfs(int nod)
{
    int hson = 0;
    size[nod] = 1;

    for(int son: G[nod])
    {
        if ( father[son] == 0 )
        {
            father[son] = nod;
            depth[son] = depth[nod] + 1;

            dfs(son);

            if ( size[hson] < size[son] )
                hson = son;
        }
    }

    if (hson == 0)
        path[nod] = NrPaths++;
    else
        path[nod] = path[hson];

    pos_in_path[nod] = length_path[ path[nod] ]++;
}

void build_heavy()
{
    father[1] = 1;
    depth[1] = 0;
    dfs(1);

    for ( int i = 1; i <= N; ++i )
    {
        pos_in_path[i] = length_path[ path[i] ] - pos_in_path[i] - 1;

        if ( pos_in_path[i] == 0 )
            start_node[ path[i] ] = i;
    }
}

void build_segment_trees()
{
    vector< vector<int> > pathValues(NrPaths);

    for ( int i = 0; i < NrPaths; ++i )
        pathValues[i] = vector<int>(length_path[i]);

    for ( int i = 1; i <= N; ++i )
        pathValues[ path[i] ][ pos_in_path[i] ] = value[i];

    for ( int i = 0; i < NrPaths; ++i )
        ST.push_back(SegmentTree(pathValues[i]));
}

void update(int nod, int new_val)
{
    value[nod] = new_val;
    ST[ path[nod] ].update(pos_in_path[nod], new_val);
}

int query(int x, int y)
{
    if ( depth[ start_node[ path[x] ] ] < depth[ start_node[ path[y] ] ] )
        swap(x, y);

    if ( path[x] == path[y] )
        return ST[ path[x] ].query(min(pos_in_path[x], pos_in_path[y]), max(pos_in_path[x], pos_in_path[y]));
    else
        return Merge(ST[ path[x] ].query(0, pos_in_path[x]), query(father[ start_node[ path[x] ] ], y));
}

int main()
{
    ifstream in("heavypath.in");
    ofstream out("heavypath.out");

    in.sync_with_stdio( false );

    in >> N >> Q;

    for ( int i = 1; i <= N; ++i )
        in >> value[i];

    for ( int i = 1, a, b; i < N; ++i )
    {
        in >> a >> b;

        G[a].push_back( b );
        G[b].push_back( a );
    }

    build_heavy();
    build_segment_trees();

    for ( int i = 1, tip, a, b; i <= Q; ++i )
    {
        in >> tip >> a >> b;

        if ( tip == 0 )
        {
            update( a, b );
        }
        else
        {
            out << query( a, b ) << "\n";
        }
    }

    return 0;
}