Cod sursa(job #2733382)

Utilizator gavra_bogdanBogdan Gavra gavra_bogdan Data 30 martie 2021 12:25:35
Problema Heavy Path Decomposition Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.67 kb
#include <fstream>
#include <vector>
#include <cmath>
#include <algorithm>
#define MAX(a, b) (((a)>(b))?(a):(b))

const int N = 1e5 + 5;

std::vector<int>l[N], bigboi;
std::vector<std::vector<int>>hl;
int bigboss[N], k, v[N], col[N];
int mx[N], n, m, tata[N], poz[N];
int euler[2*N], e, f_app[N];
int rmq[21][N], h[N];
int aint[4*N], sz, cnt;

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

void dfs(int node = 1, int from = 0) {
    euler[++e] = node;
    f_app[node] = e;
    tata[node] = from;
    h[node] = h[from] + 1;
    rmq[0][e] = node;
    if(l[node].size()==1 and l[node][0]==from) {
        bigboss[++k] = node;
        hl.push_back({node});
        mx[node] = 1;
        col[node] = k;
        return;
    }
    int c, mmax=0, mmxx;
    for(int to:l[node]) if(from!=to) {
        dfs(to, node);
        euler[++e] = node;
        rmq[0][e] = node;
        if(mx[to]>mmax) {
            if(mmax+1>mmxx) mmxx=mmax+1;
            mmax = mx[to], c = to;
        }
        else if(mx[to]+1>mmxx) mmxx=mx[to]+1;
    }
    bigboss[col[c]]=node;
    hl[col[c]].push_back(node);
    mx[node] = mmxx;
    col[node] = col[c];
}

int Min(int a, int b) {
    return ((h[a]>h[b])?b:a);
}

int Lca(int from, int to) {
    if(f_app[from]>f_app[to]) std::swap(from, to);
    int lg = (int)log2(f_app[to]-f_app[from]+1);
    return Min(rmq[lg][f_app[from]], rmq[lg][f_app[to]-(1<<lg)+1]);
}

void build(int node, int st, int dr) {
    if(st>dr) return;
    if(st==dr) {
        aint[node] = bigboi[st-1];
        return;
    }
    int mij = (st+dr)>>1;
    build(2*node, st, mij);
    build(2*node+1, mij+1, dr);
    aint[node] = MAX(aint[2*node], aint[2*node+1]);
}

void update(int node, int st, int dr, int x, int y) {
    if(st>dr or x<st or x>dr) return;
    if(st==dr) {
        aint[node]=y;
        return;
    }
    int mij = (st+dr)>>1;
    if(x<=mij) update(2*node, st, mij, x, y);
    else update(2*node+1, mij+1, dr, x, y);
    aint[node] = MAX(aint[2*node], aint[2*node+1]);
}

int query(int node, int st, int dr, int x, int y) {
    if(x<=st and dr<=y) return aint[node];
    if(y<st or dr<x) return 0;
    int mij = (st+dr)>>1;
    int ans = 0;
    if(x<=mij) ans = MAX(ans, query(2*node, st, mij, x, y));
    if(mij<y) ans = MAX(ans, query(2*node+1, mij+1, dr, x, y));
    return ans;
}

void solve(int from, int to) {
    int lca = Lca(from, to), ans = 0;
    while(col[from]!=col[lca]) {
        ans = MAX(ans, query(1, 1, sz, poz[bigboss[col[from]]], poz[from]));
        from = tata[bigboss[col[from]]];
    }
    ans = MAX(ans, query(1, 1, sz, poz[lca], poz[from]));
    while(col[to]!=col[lca]) {
        ans = MAX(ans, query(1, 1, sz, poz[bigboss[col[to]]], poz[to]));
        to = tata[bigboss[col[to]]];
    }
    ans = MAX(ans, query(1, 1, sz, poz[lca], poz[to]));
    fout<<ans<<"\n";
}

int main() {
    hl.push_back({0});
    std::ios::sync_with_stdio(0);
    fin.tie(0);
    fout.tie(0);
    int from, to, op, x, y;
    fin>>n>>m;
    for(int i=1;i<=n;i++) fin>>v[i];
    for(int i=1;i<n;i++) {
        fin>>from>>to;
        l[from].push_back(to);
        l[to].push_back(from);
    }
    dfs();
    for(int j=1;(1<<j)<=e;j++)
        for(int i=1;i+(1<<j)-1<=e;i++)
            rmq[j][i] = Min(rmq[j-1][i], rmq[j-1][i+(1<<(j-1))]);
    for(int i=1;i<=k;i++) sz+=hl[i].size(), std::reverse(hl[i].begin(), hl[i].end());
    for(int i=1;i<=k;i++)
        for(int to:hl[i])
            poz[to] = ++cnt, bigboi.push_back(v[to]);
    build(1, 1, sz);
    while(m--) {
        fin>>op>>x>>y;
        if(!op) update(1, 1, sz, poz[x], y);
        else solve(x, y);
    }
}