Cod sursa(job #2206758)

Utilizator Chirita_MateiChirita Matei Chirita_Matei Data 23 mai 2018 18:38:03
Problema Heavy Path Decomposition Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.29 kb
#include <bits/stdc++.h>

using namespace std;
ofstream fout("heavypath.out");
ifstream fin("heavypath.in");

const int NMax = 100010;
int niv[NMax];
int sub[NMax];
int path[NMax];
vector<int> P[NMax];
vector<int> G[NMax];
int parent[NMax];
int val[NMax];
int k, n, m, x, y, o;
vector<int> T[NMax];
int pos[NMax];

void makePaths(int node, int prev, int level){
    int maxi = 0;
    int connect = 0;

    niv[node] = level;

    for(int i = 0; i < G[node].size(); i++){
        int next = G[node][i];
        if(next == prev) continue;

        makePaths(next, node, level + 1);
        if(sub[next] > maxi){
            maxi = sub[next];
            connect = next;
        }
    }

    if(!maxi){
        P[++k].push_back(node);
        path[node] = k;
        sub[node] = 1;
        return;
    }

    P[path[connect]].push_back(node);
    path[node] = path[connect];
    sub[node] = sub[connect];

    for(int i = 0; i < G[node].size(); i++){
        int next = G[node][i];
        if(next == prev) continue;

        if(next != connect){
            parent[path[next]] = node;
        }
    }
}

void reversePaths()
{
    for(int i = 1; i <= k; i++){
        reverse(P[i].begin(), P[i].end());
    }
}

void update(vector<int> &t, int pos, int st, int dr, int val, int node){
    if(st == dr){
        t[pos] = val;
        return;
    }

    int mid = (st + dr) / 2;

    if(node <= mid) update(t, pos * 2, st, mid, val, node);
    else update(t, pos * 2 + 1, mid + 1, dr, val, node);

    t[pos] = max(t[pos * 2], t[pos * 2 + 1]);
}

int maxim(vector<int> &t, int st, int dr, int l, int r, int pos){
    if(st==l && dr==r)
    {
        return t[pos];
    }

    int mij = (l+r)/2, nr1 = 0, nr2 = 0;

    if(st <= mij) nr1 = maxim(t, st, min(dr, mij), l, mij, pos * 2);
    if(dr > mij)  nr2 = maxim(t, max(mij+1, st), dr, mij + 1, r, pos * 2 + 1);

    return max(nr1,nr2);
}

void makeTrees(){
    for(int i = 1; i <= k; i++){
        for(int j = 0; j < P[i].size(); j++){
            T[i].resize(4*P[i].size() + 1);
            update(T[i], 1, 1, P[i].size(), val[P[i][j]], j + 1);
            pos[P[i][j]] = j + 1;
        }
    }
}

int solve2(int x, int y){
    int rez = val[x];


    while(x != y){
        if(niv[parent[path[x]]] < niv[parent[path[y]]] || parent[path[x]] == 0) swap(x, y);

        if(path[x] == path[y]){
            rez = max(rez, maxim(T[path[x]], min(pos[x], pos[y]), max(pos[x],pos[y]), 1, P[path[x]].size(), 1));
            y = x;
        }

        else{
            rez = max(rez, maxim(T[path[x]], 1, pos[x], 1, P[path[x]].size(), 1));
            x = parent[path[x]];
        }
    }

    return rez;
}

void query(){
    for(int i = 1; i <= m; i++){
        fin >> o >> x >> y;
        if(o == 0){
            val[x] = y;
            update(T[path[x]], 1, 1, P[path[x]].size(), y, pos[x]);
        }

        else{
            fout << solve2(x, y) << '\n';
        }
    }
}

int main()
{
    fin >> n >> m;

    for(int i = 1; i <= n; i++) fin >> val[i];
    for(int i = 1; i < n; i++){
        fin >> x >> y;

        G[x].push_back(y);
        G[y].push_back(x);
    }

    makePaths(1, 0, 0);
    reversePaths();
    makeTrees();
    query();


    return 0;
}