Cod sursa(job #1166066)

Utilizator Impaler_009Mihai Nitu Impaler_009 Data 3 aprilie 2014 10:45:09
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.7 kb
#include <fstream>
#include <vector>
#include <algorithm>

#define maxn 100001
#define vint vector<int>::iterator

using namespace std;

ifstream fin ("heavypath.in");
ofstream fout ("heavypath.out");

int n,m;
int v[maxn],wh[maxn],depth[maxn];
vector<int> T[maxn];

vector<int> P[maxn];
int arb[4*maxn],arbpos[maxn],parent[maxn];
int l,r,ans,jump,total,val,a,b,t,x,y;

int dfs (int x, int father, int lvl)
{
    depth[x] = lvl;
    bool leaf = 1;
    int sum = 0, heavy = 0, heavysize= 0;

    for (vint it = T[x].begin (); it != T[x].end(); ++it )
    {
        if (*it != father)
        {
            leaf = 0;

            int childsize = dfs (*it,x,lvl+1);

            if (childsize > heavysize)
            {
                heavy = *it;
                heavysize = childsize;
            }

            sum += childsize;
        }
    }

    if (leaf)
    {
        ++total;
        P[total].push_back (x);
        wh[x] = total;
    }
    else
    {
        P[wh[heavy]].push_back (x);
        wh[x] = wh[heavy];

        for (vint it = T[x].begin (); it != T[x].end(); ++it)
        {
            if (*it != father && *it != heavy)
            {
                parent[wh[*it]] = x;
            }
        }
    }

    return sum+1;
}

void make_tree (int node, int left, int right)
{
    if (left == right)
    {
        arb[node+jump] = v[P[l][left-1]];
        return;
    }

    int mid = (left + right)/2;

    make_tree (node<<1,left,mid);
    make_tree ((node<<1)+1,mid+1,right);

    arb[node+jump]  = max(arb[(node<<1)+jump],arb[(node<<1)+1+jump]);
}

void build_trees ()
{
    jump = 0;
    for (int i = 1; i<=total; ++i)
    {
        l=i;

        reverse (P[i].begin(),P[i].end());

        make_tree (1,1,P[i].size());
        arbpos[i] = jump;

        jump += 4*P[i].size();
    }
}

void update (int node, int left, int right)
{
    if (left == right)
    {
        arb[node+jump] = val;
        return;
    }

    int mid = (left + right)/2;

    if (l <= mid)
      update (node<<1,left,mid);
    else update ((node<<1)+1,mid+1,right);

    arb[node+jump] = max (arb[(node<<1)+jump],arb[(node<<1)+1+jump]);
}

void query (int node, int left, int right)
{
    if (l <= left && right <= r)
    {
        ans = max (ans,arb[node+jump]);
        return;
    }

    int mid = (left + right)/2;

    if (l <= mid)
      query (node<<1,left,mid);
    if (r > mid)
      query ((node<<1)+1,mid+1,right);
}

int main()
{
    fin>>n>>m;

    for (int i=1; i<=n; ++i)
      fin>>v[i];

    for (int i=1; i<n; ++i)
    {
        fin>>a>>b;
        T[a].push_back (b);
        T[b].push_back (a);
    }

    dfs (1,0,1);
    build_trees ();

    for (int i=1; i<=m; ++i)
    {
        fin>>t;

        if (!t)
        {
            fin>>x>>val;

            jump = arbpos[wh[x]];
            l = depth[x] - depth[parent[wh[x]]];

            update (1,1,P[wh[x]].size());
        }
        else
        {
            fin>>x>>y;

            ans = 0;

            while (wh[x] != wh[y])
            {
                if (depth[parent[wh[x]]] < depth[parent[wh[y]]])
                 swap (x,y);

                l = 1;
                r = depth[x] - depth[parent[wh[x]]];
                jump = arbpos[wh[x]];

                query (1,1,P[wh[x]].size());

                x = parent[wh[x]];
            }

            l = depth[x] - depth[parent[wh[x]]];
            r = depth[y] - depth[parent[wh[y]]];

            if (l > r)
              swap (l,r);

            jump = arbpos[wh[x]];

            query (1,1,P[wh[x]].size());


            fout<<ans<<"\n";
        }
    }
}