Cod sursa(job #1550795)

Utilizator fanache99Constantin-Buliga Stefan fanache99 Data 14 decembrie 2015 18:37:09
Problema Heavy Path Decomposition Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 4.15 kb
#include<cstdio>
#include<vector>
#include<algorithm>
#define MAXN 100010
using namespace std;
vector<int> g[MAXN],path[MAXN],arbint[MAXN];
int value[MAXN],which[MAXN],paths=0,weight[MAXN],depth[MAXN],position[MAXN],dad[MAXN];
int maxim(int a,int b){
    if(a<b)
        return b;
    return a;
}
int minim(int a,int b){
    if(a<b)
        return a;
    return b;
}
void decompose(int node,int up){
    int dim=g[node].size(),i,where,maxim=-1;
    weight[node]=1;
    depth[node]=depth[up]+1;
    if(dim==1&&node!=1){
        paths++;
        path[paths].push_back(-1);
        path[paths].push_back(node);
        which[node]=paths;
        return;
    }
    for(i=0;i<dim;i++){
        if(g[node][i]==up)
            continue;
        decompose(g[node][i],node);
        weight[node]+=weight[g[node][i]];
        if(weight[g[node][i]]>maxim){
            maxim=weight[g[node][i]];
            where=which[g[node][i]];
        }
    }
    path[where].push_back(node);
    which[node]=where;
    for(i=0;i<dim;i++){
        if(g[node][i]==up||which[g[node][i]]==where)
            continue;
        dad[which[g[node][i]]]=node;
    }
}
bool cmp(int a,int b){
    if(depth[a]<depth[b])
        return true;
    return false;
}
void initialize(int which_path,int left,int right){
    int middle=(left+right)/2;
    arbint[which_path].push_back(-1);
    if(left==right)
        return;
    initialize(which_path,left,middle);
    initialize(which_path,middle+1,right);
}
void build_arbint(int which_path,int node,int left,int right){
    int middle=(left+right)/2;
    arbint[which_path].push_back(-1);
    if(left==right){
        arbint[which_path][node]=value[path[which_path][left]];
        return;
    }
    build_arbint(which_path,2*node,left,middle);
    build_arbint(which_path,2*node+1,middle+1,right);
    arbint[which_path][node]=maxim(arbint[which_path][2*node],arbint[which_path][2*node+1]);
}
void update(int which_path,int node,int left,int right,int index,int add){
    int middle=(left+right)/2;
    if(left==right){
        arbint[which_path][node]=add;
        return;
    }
    if(index<=middle)
        update(which_path,2*node,left,middle,index,add);
    else
        update(which_path,2*node+1,middle+1,right,index,add);
    arbint[which_path][node]=maxim(arbint[which_path][2*node],arbint[which_path][2*node+1]);
}
int query(int which_path,int node,int left,int right,int left_index,int right_index){
    int middle=(left+right)/2,answer=-1;
    if(left_index<=left&&right<=right_index)
        return arbint[which_path][node];
    if(left_index<=middle&&right_index>=left)
        answer=maxim(answer,query(which_path,2*node,left,middle,left_index,right_index));
    if(right_index>middle&&left_index<=right)
        answer=maxim(answer,query(which_path,2*node+1,middle+1,right,left_index,right_index));
    return answer;
}
int get_answer(int x,int y){
    int temp;
    if(which[x]==which[y])
        return query(which[x],1,1,path[which[x]].size()-1,minim(position[x],position[y]),maxim(position[x],position[y]));
    if(depth[dad[which[x]]]<depth[dad[which[y]]]){
        temp=x;
        x=y;
        y=temp;
    }
    return maxim(query(which[x],1,1,path[which[x]].size()-1,1,position[x]),get_answer(dad[which[x]],y));
}
int main(){
    freopen("heavypath.in","r",stdin);
    freopen("heavypath.out","w",stdout);
    int n,t,q,i,j,a,dim,b,x,y,op;
    scanf("%d%d",&n,&t);
    for(i=1;i<=n;i++)
        scanf("%d",&value[i]);
    for(i=1;i<n;i++){
        scanf("%d%d",&a,&b);
        g[a].push_back(b);
        g[b].push_back(a);
    }
    decompose(1,0);
    for(i=1;i<=paths;i++){
        sort(path[i].begin(),path[i].end(),cmp);
        dim=path[i].size();
        for(j=1;j<dim;j++)
            position[path[i][j]]=j;
        arbint[i].push_back(-1);
        initialize(i,1,dim-1);
        build_arbint(i,1,1,dim-1);
    }
    for(q=1;q<=t;q++){
        scanf("%d%d%d\n",&op,&x,&y);
        if(op==0){
            value[x]=y;
            update(which[x],1,1,path[which[x]].size()-1,x,y);
        }
        else
            printf("%d\n",get_answer(x,y));
    }
    return 0;
}