Cod sursa(job #2515887)

Utilizator bogdi1bogdan bancuta bogdi1 Data 29 decembrie 2019 18:23:18
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.19 kb
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> g[100005];
vector<int> pathuri[100005];
int carepath[100005];
int pozpath[100005];
int level[100005];
int tata[100005];
int dim[100005];
int parentul[100005];
int offset[100005];
int nr;
void dfs(int nod, int parent, int lvl)
{
    level[nod]=lvl;
    tata[nod]=parent;
    dim[nod]=1;
    int maxx=0,ii;
    for(int i=0; i<g[nod].size(); i++)
        if(level[g[nod][i]]==0){
            dfs(g[nod][i], nod, lvl+1);
            dim[nod]+=dim[g[nod][i]];
            if(maxx<dim[g[nod][i]]){
                maxx=dim[g[nod][i]];
                ii=g[nod][i];
            }
        }
    if(maxx==0){
        pathuri[++nr].push_back(nod);
        carepath[nod]=nr;
        parentul[nr]=tata[nod];
    }
    else{
        pathuri[carepath[ii]].push_back(nod);
        carepath[nod]=carepath[ii];
        parentul[carepath[ii]]=tata[nod];
    }
}
struct Interval
{
    int maxx;
};
int v[100005];
Interval arbint[400005];
int n;
Interval create(int value)
{
    return Interval{
        value,
    };
}
Interval join(const Interval &left, const Interval &right)
{
    return Interval{
        max(left.maxx, right.maxx),
    };
}
void update(int nod, int st, int dr, int index, int value, int add)
{
    if(st==dr)
        arbint[add+nod]=create(value);
    else{
        int mij=(st+dr)/2;
        if(index<=mij)
            update(2*nod, st, mij, index, value, add);
        else
            update(2*nod+1, mij+1, dr, index, value, add);
        arbint[add+nod]=join(arbint[add+2*nod], arbint[add+2*nod+1]);
    }
}
Interval query(int nod, int st, int dr, int left, int right, int add)
{
    if(st==left && dr==right)
        return arbint[add+nod];
    else{
        int mij=(st+dr)/2;
        if(right<=mij)
            return query(2*nod, st, mij, left, right, add);
        else{
            if(mij<left)
                return query(2*nod+1, mij+1, dr, left, right, add);
            else
                return join(query(2*nod, st, mij, left, mij, add), query(2*nod+1, mij+1, dr, mij+1, right, add));
        }
    }
}
int main()
{   freopen("heavypath.in", "r", stdin);
    freopen("heavypath.out", "w", stdout);
    int n,m,i,x,y,j,tip,ans;
    scanf("%d%d", &n, &m);
    for(i=1; i<=n; i++)
        scanf("%d", &v[i]);
    for(i=1; i<n; i++){
        scanf("%d%d", &x, &y);
        g[x].push_back(y);
        g[y].push_back(x);
    }
    dfs(1, 0, 1);
    for(i=1; i<=nr; i++){
        offset[i]=offset[i-1]+4*pathuri[i-1].size();
        for(j=0; j<pathuri[i].size()/2; j++){
            swap(pathuri[i][j], pathuri[i][pathuri[i].size()-1-j]);
            pozpath[pathuri[i][j]]=j;
            pozpath[pathuri[i][pathuri[i].size()-1-j]]=pathuri[i].size()-1-j;
        }
        pozpath[pathuri[i][j]]=j;
    }
    for(i=1; i<=n; i++)
        update(1, 0, pathuri[carepath[i]].size()-1, pozpath[i], v[i], offset[carepath[i]]);
    for(i=1; i<=m; i++){
        scanf("%d%d%d", &tip, &x, &y);
        if(tip==0)
            update(1, 0, pathuri[carepath[x]].size()-1, pozpath[x], y, offset[carepath[x]]);
        else{
            ans=0;
            while(1){
                if(carepath[x]==carepath[y]){
                    int a=min(pozpath[x], pozpath[y]);
                    int b=max(pozpath[x], pozpath[y]);
                    ans=max(ans, query(1, 0, pathuri[carepath[x]].size()-1, a, b, offset[carepath[x]]).maxx);
                    break;
                }
                else{
                    if(level[parentul[carepath[x]]]>level[parentul[carepath[y]]]){
                        int a=pozpath[x];
                        ans=max(ans, query(1, 0, pathuri[carepath[x]].size()-1, 0, a, offset[carepath[x]]).maxx);
                        x=parentul[carepath[x]];
                    }
                    else{
                        int a=pozpath[y];
                        ans=max(ans, query(1, 0, pathuri[carepath[y]].size()-1, 0, a, offset[carepath[y]]).maxx);
                        y=parentul[carepath[y]];
                    }
                }
            }
            printf("%d\n", ans);
        }
    }
    return 0;
}