Cod sursa(job #2378824)

Utilizator tifui.alexandruTifui Ioan Alexandru tifui.alexandru Data 12 martie 2019 17:35:10
Problema Heavy Path Decomposition Scor 80
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.44 kb
#include <bits/stdc++.h>
#define Nmax 100005
#define ls (((node+1)<<1)-1)
#define rs (ls+1)

using namespace std;


ifstream f("heavypath.in");
ofstream g("heavypath.out");

int N,M,path_sz,tree_no,look_for,lsh,rsh;
list <int> tree[Nmax];
int v[Nmax],weight[Nmax],lvl[Nmax],parent[Nmax],no_path[Nmax],pos[Nmax];
vector <int> Segment_Tree[Nmax],path[Nmax];

void read_data(){

    f>>N>>M;
    for(int i=1;i<=N;i++)
        f>>v[i];

    for(int x,y,i=1;i<N;i++){

        f>>x>>y;
        tree[x].push_back(y);
        tree[y].push_back(x);
    }
}

void build(int lo, int hi, int node){

    if(lo==hi)
        Segment_Tree[tree_no][node]=v[path[tree_no][lo]];
    else{

        int mid=(lo+hi)>>1;
        build(lo,mid,ls);
        build(mid+1,hi,rs);

        Segment_Tree[tree_no][node]=max(Segment_Tree[tree_no][ls],Segment_Tree[tree_no][rs]);
    }
}

void update(int lo, int hi, int node){

    if(lo==hi)
        Segment_Tree[tree_no][node]=v[path[tree_no][lo]];
    else{

        int mid=(lo+hi)>>1;

        if(look_for<=mid)
            update(lo,mid,ls);
        else
            update(mid+1,hi,rs);

        Segment_Tree[tree_no][node]=max(Segment_Tree[tree_no][ls],Segment_Tree[tree_no][rs]);
    }
}

int query(int lo, int hi, int node){

    if(lsh<=lo and hi<=rsh)
        return Segment_Tree[tree_no][node];
    else{

        int mid=(lo+hi)>>1,m1=INT_MIN,m2=INT_MIN;

        if(lsh<=mid) m1=query(lo,mid,ls);
        if(mid<rsh) m2=query(mid+1,hi,rs);

        return max(m1,m2);
    }
}

void DFS(int node){

    bool is_leaf=true;
    int next_node=0;
    weight[node]=1;

    for(list <int> :: iterator it=tree[node].begin();it!=tree[node].end();++it)
        if(!lvl[*it]){

            lvl[*it]=lvl[node]+1;
            is_leaf=false;
            parent[*it]=node;

            DFS(*it);

            if(weight[*it]>weight[next_node])
                next_node=*it;

            weight[node]+=weight[*it];
        }

    if(is_leaf){

        path[++path_sz].push_back(node);
        no_path[node]=path_sz;
    }
    else{

        path[no_path[next_node]].push_back(node);
        no_path[node]=no_path[next_node];
    }
}

void heavy_path_dec(){

    lvl[1]=1;
    DFS(1);

    for(int i,k=1;k<=path_sz;k++){

        reverse(path[k].begin(),path[k].end());

        for(i=0;i<(int)path[k].size();i++)
            pos[path[k][i]]=i;

        Segment_Tree[k].resize(4*path[k].size());

        tree_no=k;
        build(0,path[k].size()-1,0);
    }
}

int get_ans(int x, int y){

    int ans=INT_MIN;

    while(no_path[x]!=no_path[y]){

        if(lvl[path[no_path[x]][0]]<lvl[path[no_path[y]][0]])
            swap(x,y);

        lsh=0;
        rsh=pos[x];
        tree_no=no_path[x];

        ans=max(ans,query(0,path[tree_no].size()-1,0));
        x=parent[path[tree_no][0]];
    }

    lsh=min(pos[x],pos[y]);
    rsh=max(pos[x],pos[y]);
    tree_no=no_path[x];

    ans=max(ans,query(0,path[tree_no].size()-1,0));

    return ans;
}

void solve_queries(){

    int op,x,y;
    while(M--){

        f>>op>>x>>y;

        if(!op){

            v[x]=y;
            tree_no=no_path[x];
            look_for=pos[x];

            update(0,path[tree_no].size()-1,0);
        }
        else g<<get_ans(x,y)<<'\n';
    }
}

int main(){

    read_data();
    heavy_path_dec();
    solve_queries();

    return 0;
}