Cod sursa(job #2440381)

Utilizator CharacterMeCharacter Me CharacterMe Data 18 iulie 2019 12:18:05
Problema Heavy Path Decomposition Scor 10
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.27 kb
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <queue>
using namespace std;
int n, m, i, j, k, val[100001], pathnum[100001], pathpos[100001], heavy[100001], dad[100001], height[100001], vf;
vector<int> graph[100001], pathlist[100001];
class Tree{
public:
    int *v, sz;
    void change(int a, int b, int pos, int ch, int position);
    int get(int a, int b, int left, int right, int position);
    void update(int pos, int ch){
        change(1, sz, pos, ch, 1);
    }
    int query(int left, int right){
        return get(1, sz, left, right, 1);
    }
    void setsize(int sz){
        this->sz=sz;
        v=(int *)malloc(4*sz+20);
        return;
    }
}tree[100005];
queue<int> q;
void findheavy(int node);
void dfs(int node);
int main()
{
    freopen("heavypath.in", "r", stdin);
    freopen("heavypath.out", "w", stdout);
    scanf("%d%d", &n, &m);
    for(i=1; i<=n; ++i) scanf("%d", &val[i]);
    height[0]=-1;
    for(i=2; i<=n; ++i){
        int x, y;
        scanf("%d%d", &x, &y);
        graph[x].push_back(y);
        graph[y].push_back(x);
    }
    findheavy(1);
    q.push(1);
    while(!q.empty()){++vf; pathlist[vf].push_back(dad[q.front()]); dfs(q.front()); q.pop();}
    for(i=1; i<=vf; ++i){
        tree[i].setsize(pathlist[i].size()-1);
        for(j=1; j<=tree[i].sz; ++j) tree[i].update(j, val[pathlist[i][j]]);
    }
    for(i=1; i<=m; ++i){
        int t, x, y;
        scanf("%d%d%d", &t, &x, &y);
        if(!t) tree[pathnum[x]].update(pathpos[x], y);
        else{
            int sol=-1;
            while(pathnum[x]!=pathnum[y]){
                if(height[pathlist[pathnum[x]][0]]<height[pathlist[pathnum[y]][0]]) swap(x, y);
                sol=max(sol, tree[pathnum[x]].query(1, pathpos[x]));
                x=pathlist[pathnum[x]][0];
            }
            if(height[x]<height[y]) swap(x, y);
            sol=max(sol, tree[pathnum[x]].query(pathpos[y], pathpos[x]));
            printf("%d\n", sol);
        }
    }
    return 0;
}
void Tree::change(int a, int b, int pos, int ch, int position){
    int mid=(a+b)/2;
    if(a==b) {v[position]=ch; return;}
    if(pos<=mid) change(a, mid, pos, ch, 2*position);
    else change(mid+1, b, pos, ch, 2*position+1);
    v[position]=max(v[2*position], v[2*position+1]);
    return;
}
int Tree::get(int a, int b, int left, int right, int position){
    int mid=(a+b)/2;
    if(a==left && b==right) return v[position];
    if(right<=mid) return get(a, mid, left, right, 2*position);
    else if(left>mid) return get(mid+1, b, left, right, 2*position+1);
    else return max(get(a, mid, left, mid, 2*position), get(mid+1, b, mid+1, right, 2*position+1));
}
void findheavy(int node){
    ++heavy[node];
    for(auto i:graph[node]) if(i!=dad[node]){
        dad[i]=node; height[i]=height[node]+1;
        findheavy(i);
        heavy[node]+=heavy[i];
    }
    return;
}
void dfs(int node){
    pathpos[node]=pathlist[vf].size();
    pathnum[node]=vf;
    pathlist[vf].push_back(node);
    int next=0, mx=-1;
    for(auto i:graph[node]){
        if(i!=dad[node] && heavy[i]>mx){
            mx=heavy[i];
            next=i;
        }
    }
    for(auto i:graph[node]) if(i!=dad[node] && i!=next) q.push(i);
    if(next)dfs(next);
}