Cod sursa(job #967723)

Utilizator VisuianMihaiMihai Visuian VisuianMihai Data 28 iunie 2013 12:36:56
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.36 kb
#include <fstream>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");

vector<int>g[100001], p[100001];
int w[100001], niv[100001], where[100001], n, m, x, y, num_paths=1, Parent[100001], v[100001];
int arb[100001*4], sol, poz[100001], op;
bool used[100001], is_free[100001];

bool cmp(int a, int b){
    return w[a] > w[b];
}

void Dfs(int x)
{
    used[x]=1;
    w[x]=1;
    for(vector<int>::iterator it=g[x].begin(); it<g[x].end(); it++ )
        if(!used[*it])
        {
            niv[*it]=niv[x]+1;
            Dfs(*it);
            w[x]+=w[*it];
        }
}

void Update(int nod, int left, int right, int pos, int val, int decalaj)
{
    if(left==right)
    {
        arb[nod+decalaj]=val;
        return;
    }
    int mid = (left+right)/2;
    if ( pos <= mid)
        Update(2*nod,left,mid,pos,val,decalaj);
    else
        Update(2*nod+1,mid+1,right,pos,val,decalaj);
    arb[nod+decalaj]=max(arb[2*nod+1+decalaj],arb[2*nod+decalaj]);
}
int query(int nod, int left, int right, int qleft, int qright, int decalaj)
{
    if(qleft <= left && right <= qright)
        return arb[nod + decalaj];
    int mid = (left+right)/2, rez = 0;
    if(qleft <= mid)
        rez = max(rez, query(nod * 2, left, mid, qleft, qright, decalaj));
    if(mid < qright)
        rez = max(rez, query(nod * 2 + 1, mid + 1, right, qleft, qright, decalaj));
    return rez;
}

void Heavy_Path(int x, int path)
{
    used[x]=1;
    where[x]=path;
    p[path].push_back(x);
    for(vector<int>::iterator it=g[x].begin(); it<g[x].end(); it++ )
        if(!used[*it])
        {
            if(!is_free[x])
            {
                is_free[x]=1;
                Heavy_Path(*it,path);
            }
            else
            {
                ++num_paths;
                Parent[num_paths]=x;
                Heavy_Path(*it,num_paths);
            }
        }
}

void Make_paths()
{
    niv[1]=1;
    Dfs(1);
    memset(used,0,sizeof(used));
    for(int i = 1; i<= n; i++ )
        sort(g[i].begin(), g[i].end(), cmp);
    Heavy_Path(1,1);
    for(int i = 1; i<= num_paths; i++ )
    {
        if(i>1)
            poz[i]=poz[i-1]+p[i-1].size()*4;
        for(vector<int>::iterator it=p[i].begin(); it<p[i].end(); it++)
            Update(1,1,(int)p[i].size(),niv[*it]-niv[Parent[where[*it]]],v[*it],poz[i]);
    }
}

int main()
{
    fin>>n>>m;
    for(int i = 1; i<= n; i++)
        fin >> v[i];
    for(int i = 1; i< n; i++)
    {
        fin >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    Make_paths();
    for(int i = 1; i<= m; i++ )
    {
        fin >> op >> x >> y;
        if(!op)
            Update(1,1,(int)p[where[x]].size(),niv[x]-niv[Parent[where[x]]],y,poz[where[x]]);
        else
        {
            sol=0;
            while(where[x] != where[y])
            {
                if(niv[Parent[where[x]]]<niv[Parent[where[y]]])
                    swap(x,y);
                sol = max(sol,query(1,1,(int)p[where[x]].size(),1,niv[x]-niv[Parent[where[x]]],poz[where[x]]));
                x = Parent[where[x]];
            }
            if ( niv[x] > niv[y] )
                swap(x,y);
            sol = max(sol,query(1,1,(int)p[where[x]].size(),niv[x]-niv[Parent[where[x]]],niv[y]-niv[Parent[where[x]]],poz[where[x]]));

            fout<<sol<<'\n';
        }
    }
    fin.close();
    fout.close();
    return 0;
}