Cod sursa(job #2585967)

Utilizator IoanaDraganescuIoana Draganescu IoanaDraganescu Data 19 martie 2020 15:56:47
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.82 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>

using namespace std;

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

const int NMax = 100000;

vector <int> g[NMax + 5], c[NMax + 5];
int n, m, nrchains;
int v[NMax + 5], w[NMax + 5], chain[NMax + 5], level[NMax + 5];
int length[NMax + 5], father[NMax + 5], start[NMax + 5];
int aint[4 * NMax + 5];
bool use[NMax + 5];

void Read(){
    fin >> n >> m;
    for (int i = 1; i <= n; i++)
        fin >> v[i];
    for (int i = 1; i < n; i++){
        int x, y;
        fin >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
}

void DFS(int node){
    int weight = 1, maxweight = 0, son = 0;
    use[node] = 1;
    for (auto other : g[node])
        if (!use[other]){
            level[other] = level[node] + 1;
            DFS(other);
            if (w[other] > maxweight){
                maxweight = w[other];
                son = other;
            }
            weight += w[other];
        }
    w[node] = weight;
    if (weight == 1){
        chain[node] = ++nrchains;
        c[nrchains].push_back(node);
        length[nrchains] = 1;
    }
    else{
        chain[node] = chain[son];
        c[chain[node]].push_back(node);
        length[chain[node]]++;
    }
    for (auto other : g[node]){
        if (level[other] < level[node] || other == son)
            continue;
        father[chain[other]] = node;
    }
}

void Build(int node, int l, int r, int x){
    int diff = start[x];
    if (l == r){
        aint[node + diff] = v[c[x][l - 1]];
        return;
    }
    int mid = (l + r) >> 1;
    int ls = 2 * node, rs = ls + 1;
    Build(ls, l, mid, x);
    Build(rs, mid + 1, r, x);
    aint[node + diff] = max(aint[ls + diff], aint[rs + diff]);
}

void MakeChains(){
    level[1] = 1;
    DFS(1);
    for (int i = 1; i <= nrchains; i++){
        reverse(c[i].begin(), c[i].end());
        start[i] = start[i - 1] + 4 * length[i - 1];
        Build(1, 1, length[i], i);
    }
}

void Update(int node, int l, int r, int pos, int val, int x){
    int diff = start[x];
    if (l == r){
        aint[node + diff] = val;
        return;
    }
    int mid = (l + r) >> 1;
    int ls = 2 * node, rs = ls + 1;
    if (pos <= mid)
        Update(ls, l, mid, pos, val, x);
    else
        Update(rs, mid + 1, r, pos, val, x);
    aint[node + diff] = max(aint[ls + diff], aint[rs + diff]);
}

int Query(int node, int l, int r, int ql, int qr, int x){
    int diff = start[x];
    if (ql <= l && r <= qr)
        return aint[node + diff];
    int mid = (l + r) >> 1;
    int ls = 2 * node, rs = ls + 1;
    int ans = -1;
    if (ql <= mid)
        ans = max(ans, Query(ls, l, mid, ql, qr, x));
    if (qr > mid)
        ans = max(ans, Query(rs, mid + 1, r, ql, qr, x));
    return ans;

}

int Solve(int x, int y){
    int ans = -1;
    bool ok = 1;
    while (ok){
        if (chain[x] == chain[y]){
            if (level[x] < level[y])
                swap(x, y);
            ans = max(ans, Query(1, 1, length[chain[x]], level[y] - level[father[chain[y]]], level[x] - level[father[chain[x]]], chain[x]));
            ok = 0;
        }
        else{
            if (level[father[chain[x]]] < level[father[chain[y]]])
                swap(x, y);
            ans = max(ans, Query(1, 1, length[chain[x]], 1, level[x] - level[father[chain[x]]], chain[x]));
            x = father[chain[x]];
        }
    }
    return ans;
}

int main(){
    Read();
    MakeChains();
    for (int i = 1; i <= m; i++){
        int task, x, y;
        fin >> task >> x >> y;
        if (task == 0)
            Update(1, 1, length[chain[x]], level[x] - level[father[chain[x]]], y, chain[x]);
        else
            fout << Solve(x, y) << '\n';
    }
    return 0;
}