Cod sursa(job #975114)

Utilizator ericptsStavarache Petru Eric ericpts Data 19 iulie 2013 08:50:41
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.11 kb
#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;

#define forEach(G) for(__typeof(G.begin()) it = G.begin() ; it != G.end() ; ++ it)

const int MAX_N = 100100;
const int INF = (1 << 30) - 1;
typedef const int cint;
int n,m;

int val[MAX_N];

vector<int> G[MAX_N];
vector<int> comp[MAX_N];


int under[MAX_N];
bool viz[MAX_N];
int belong[MAX_N];
int lvl[MAX_N];
int sz[MAX_N];
int tail[MAX_N];
int height[MAX_N];
int base[4*MAX_N];
int * AINT;
int mem[MAX_N];
int cl;

void dfs(cint nod)
{
    int chosen = -1;
    viz[nod] = 1;
    forEach(G[nod]){
        if(!viz[*it]){
            lvl[*it] = lvl[nod] + 1;
            dfs(*it);
            under[nod] += under[*it];
            if(chosen == -1 || under[chosen] < under[*it])
                chosen = *it;
        }
    }
    if(under[nod] == 0){
        under[nod] = 1;
        belong[nod] = ++cl;
        sz[cl] = 1;
        comp[cl].push_back(nod);
        return;
    }
    belong[nod] = belong[chosen];
    sz[belong[nod]]++;
    comp[belong[nod]].push_back(nod);

    forEach(G[nod]){
        if(*it == chosen || lvl[*it] < lvl[nod])
            continue;

        tail[belong[*it]] = nod;
        height[belong[*it]] = lvl[nod];
    }

}

void build(cint nod,cint &left,cint &right,cint &path)
{
    if(left == right){
        AINT[nod] = val[comp[path][left-1]];
        return;
    }
    int mid = (left+right)/2;

    build(2*nod,left,mid,path);
    build(2*nod+1,++mid,right,path);

    AINT[nod] = max(AINT[2*nod],
                    AINT[2*nod+1]);
}

inline void build(cint &path)
{
    AINT = base + mem[path];
    build(1,1,sz[path],path);}

void update(cint nod,cint &left,cint &right,cint &pos,cint &path)
{
    if(left == right){
        AINT[nod] = val[comp[path][left-1]];
    } else {
      int mid = (left+right) / 2;

      if(pos <= mid)
            update(2*nod,left,mid,pos,path);
      else update(2*nod+1,++mid,right,pos,path);

      AINT[nod] = max(AINT[2*nod],
                      AINT[2*nod+1]);
    }
}

inline void update(cint &nod)
{
    int path = belong[nod];
    int pos = lvl[nod] - height[path];
    AINT = base + mem[path];
    update(1,1,sz[path],pos,path);
}

int query(cint nod,cint &left, cint &right, cint &lo,cint &hi)
{
    if(lo <= left && right <= hi)
        return AINT[nod];

    int mid = (left+right)/2;
    int c1 = -INF , c2 = -INF;

    if(lo <= mid)
        c1 = query(2*nod,left,mid,lo,hi);

    if(mid < hi)
        c2 = query(2*nod+1,++mid,right,lo,hi);

    if(c1 > c2)
        return c1;
    else return c2;
}

inline int query(cint &left,cint &right,cint &path)
{
    AINT = base + mem[path];
    return query(1,1,sz[path],left,right);
}

void solve()
{
    int t,x,y;
    while(m--){
        scanf("%d%d%d",&t,&x,&y);
        if(t == 0){
            val[x] = y;
            update(x);
        } else {

            int ans = 0;

            while(true){

                if(belong[x] == belong[y]){
                    if(lvl[x] > lvl[y])
                        swap(x,y);

                    const int aux =
                        query(lvl[x] - height[belong[x]],lvl[y] - height[belong[y]],belong[x]);
                    if(aux > ans)
                        ans = aux;
                    break;
                } else {

                    if(height[belong[x]] < height[belong[y]])
                        swap(x,y);

                    const int aux =
                        query(1,lvl[x] - height[belong[x]],belong[x]);

                    if(aux > ans)
                        ans = aux;

                    x = tail[belong[x]];

                }
            }
            printf("%d\n",ans);
        }
    }
}

int main()
{
    freopen("heavypath.in","r",stdin);
    freopen("heavypath.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i = 1 ; i <= n ; ++ i)
        scanf("%d",val+i);
    int x,y;
    for(int i = 1 ; i < n ; ++ i){
        scanf("%d%d",&x,&y);
        G[x].push_back(y);
        G[y].push_back(x);
    }
    lvl[1] = 1;
    dfs(1);
    for(int i = 1 ; i <= cl ; ++ i){
        reverse(comp[i].begin(),comp[i].end());
        mem[i] = mem[i-1] + sz[i-1] * 4;
        build(i);
    }
    solve();
    return 0;
}