Cod sursa(job #2822746)

Utilizator ptudortudor P ptudor Data 25 decembrie 2021 13:39:04
Problema Heavy Path Decomposition Scor 60
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.48 kb
#include <bits/stdc++.h>

using namespace std;

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

const int nmax = 100005;
int n,m,v[nmax],parent[nmax],depth[nmax],Size[nmax],heavy[nmax],pos,paths[nmax],headval[nmax];
int head[nmax],posInPaths[nmax],lowest[nmax];
vector<int> g[nmax];
void dfs(int node) {
    int maxSize = 0;
    for (auto k : g[node]) {
        if (k == parent[node]) continue;
        parent[k] = node;
        depth[k] = depth[node] + 1;
        dfs(k);
        Size[node] += Size[k];
        if (Size[k] > maxSize) {
            maxSize = Size[k];
            heavy[node] = k;
        }
    }
    Size[node]++;

}
void decomp(int node, int curHead) {
    paths[++pos] = node;
    posInPaths[node] = pos;
    head[node] = curHead;
    lowest[head[node]] = node;
    if (heavy[node] != 0) {
        decomp(heavy[node] , curHead);
    }

    for (auto k : g[node]) {
        if (k == parent[node]) continue;

        if (k != heavy[node]) {
            decomp(k , k);
        }
    }
}

struct SegTree {
    int l,r,val;
    SegTree *lChild, *rChild;
    SegTree(int l, int r) : l(l) , r(r) {
        if (l == r) {
            val = v[paths[l]];
        } else {
            int mij = (l + r) / 2;
            lChild = new SegTree(l, mij);
            rChild = new SegTree(mij + 1, r);
            val = max(lChild -> val , rChild -> val);
        }
    }
    void update(int qpos, int newVal) {
        if (qpos == l && qpos == r) {
            val = newVal;
            return;
        }

        if (qpos < l || qpos > r) return;

        lChild -> update(qpos, newVal);
        rChild -> update(qpos, newVal);
        val = max(lChild -> val , rChild -> val);
    }

    int query(int ql, int qr) {
        if (ql <= l && r <= qr) {
            return val;
        }

        if (l > qr || r < ql) {
            return 0;
        }

        return max( lChild -> query(ql, qr) , rChild -> query(ql, qr) );
    }
    SegTree() {}
};
SegTree segTree;


int pathQuerry(int u, int v) {
    int Max = -1;
    while ( true ) {
        if ( depth [ head [ u ] ] > depth [ head [ v ] ] ) swap(u,v); // depth of u's head will be smallest, so v will be lowest, so we bring him up.
        if (head[u] != head[v]) { // we bring v up
            if (v == lowest[head[v]]) {
                Max = max(Max , headval[head[v]]);
            } else {
                Max = max(Max, segTree.query(posInPaths[head[v]], posInPaths[v]));
            }
            v = parent[head[v]];
        } else {
            if (posInPaths[u] > posInPaths[v]) swap(u , v);
            Max = max(Max , segTree.query ( posInPaths [ u ] , posInPaths [ v ] ) );
            return Max;
        }
    }
}
int main() {
    in >> n >> m;

    for (int i = 1; i <= n; i++) {
        in >> v[i];
    }

    for (int i = 1; i < n; i++) {
        int u,v;
        in >> u >> v;
        g[u].push_back(v);
        g[v].push_back(u);
    }

    depth[1] = 1;
    dfs(1);
    decomp(1, 1);

    for (int i = 0; i <= n; i++) g[i].clear();

    segTree = SegTree(1 , n);

    for (int i = 1; i <= n; i++) {
        if (head[i] == i) {
            headval[i] = segTree.query(posInPaths[i] , posInPaths[lowest[i]]);
        }
    }
    for (int i = 1; i <= m; i++) {
        int t,x,y;
        in >> t >> x >> y;
        if (t == 1) {
            out << pathQuerry(x , y) << "\n";
        }
        else {
            segTree.update(posInPaths[x] , y);
            headval[head[x]] = segTree.query(posInPaths[head[x]] , posInPaths[lowest[head[x]]]);
        }
    }
    return 0;
}