Cod sursa(job #1110250)

Utilizator andreiiiiPopa Andrei andreiiii Data 17 februarie 2014 21:46:34
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.42 kb
#include <algorithm>
#include <cstdio>
#include <vector>

using namespace std;

const int N=100005;

vector <int> G[N], aint[N], paths[N];
int a[N], f[N], nr[N], path[N], npoz[N], lvlp[N], fp[N];
int n, X, Y, nrpaths;

void dfs1(int x)
{
    nr[x]=1;
    int poz=0;
    for(auto p: G[x])
    {
        if(p==f[x]) continue;
        f[p]=x;
        dfs1(p);
        nr[x]+=nr[p];
        if(nr[p]>nr[poz]) poz=p;
    }
    if(poz) path[x]=path[poz];
    else path[x]=++nrpaths;
    paths[path[x]].push_back(x);
}

void dfs2(int x)
{
    for(auto p: G[x])
    {
        if(p==f[x]) continue;
        if(path[x]!=path[p]) lvlp[path[p]]=lvlp[path[x]]+1;
        dfs2(p);
    }
}

void build(int lvl, int nod, int l, int r)
{
    if(l==r)
    {
        aint[lvl][nod]=a[paths[lvl][l]];
        return;
    }
    int mid=(l+r)/2;
    build(lvl, 2*nod, l, mid);
    build(lvl, 2*nod+1, mid+1, r);
    aint[lvl][nod]=max(aint[lvl][nod*2], aint[lvl][nod*2+1]);
}

void update(int lvl, int nod, int l, int r)
{
    if(l==r)
    {
        aint[lvl][nod]=Y;
        return;
    }
    int mid=(l+r)/2;
    if(X<=mid) update(lvl, 2*nod, l, mid);
    else update(lvl, 2*nod+1, mid+1, r);
    aint[lvl][nod]=max(aint[lvl][2*nod], aint[lvl][2*nod+1]);
}

int query(int lvl, int nod, int l, int r)
{
    if(X<=l&&r<=Y) return aint[lvl][nod];
    int mid=(l+r)/2, ret=0;
    if(X<=mid) ret=query(lvl, 2*nod, l, mid);
    if(Y>mid) ret=max(ret, query(lvl, 2*nod+1, mid+1, r));
    return ret;
}

int main()
{
    freopen("heavypath.in", "r", stdin);
    freopen("heavypath.out", "w", stdout);
    int m, i, j, x, y, op, sol;
    scanf("%d%d", &n, &m);
    for(i=1;i<=n;i++) scanf("%d", &a[i]);
    for(i=1;i<n;i++)
    {
        scanf("%d%d", &x, &y);
        G[x].push_back(y);
        G[y].push_back(x);
    }
    dfs1(1);
    for(i=1;i<=nrpaths;i++)
    {
        paths[i].push_back(0);
        reverse(paths[i].begin(), paths[i].end());
        for(vector <int>::iterator it=paths[i].begin()+1;it!=paths[i].end();it++)
        {
            npoz[*it]=it-paths[i].begin();
        }
        aint[i].resize(paths[i].size()*5-5);
        build(i, 1, 1, paths[i].size()-1);
    }
    dfs2(1);
    for(i=2;i<=n;i++)
    {
        if(path[i]!=path[f[i]])
        {
            fp[path[i]]=f[i];
        }
    }
    while(m--)
    {
        scanf("%d", &op);
        if(!op)
        {
            scanf("%d%d", &x, &Y);
            X=npoz[x];
            update(path[x], 1, 1, paths[path[x]].size()-1);
        }
        else
        {
            scanf("%d%d", &x, &y);
            sol=0;
            i=path[x];
            j=path[y];
            while(i!=j)
            {
                if(lvlp[i]<lvlp[j])
                {
                    X=1;
                    Y=npoz[y];
                    sol=max(sol, query(j, 1, 1, paths[j].size()-1));
                    y=fp[j];
                    j=path[y];
                }
                else
                {
                    X=1;
                    Y=npoz[x];
                    sol=max(sol, query(i, 1, 1, paths[i].size()-1));
                    x=fp[i];
                    i=path[x];
                }
            }
            X=min(npoz[x], npoz[y]);
            Y=max(npoz[x], npoz[y]);
            sol=max(sol, query(i, 1, 1, paths[i].size()-1));
            printf("%d\n", sol);
        }
    }
}