Cod sursa(job #2822586)

Utilizator ptudortudor P ptudor Data 24 decembrie 2021 14:00:03
Problema Heavy Path Decomposition Scor 60
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.17 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];
int head[nmax],posInPaths[nmax];
vector<vector<int>> g;
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;
    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(const vector<int> &a, int l, int r) : l(l) , r(r) {
        if (l == r) {
            val = v[a[l - 1]];
        } else {
            int mij = (l + r) / 2;
            lChild = new SegTree(a, l, mij);
            rChild = new SegTree(a, 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 segQuerry(int ) {return 1;};

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
            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;
    g.resize(n + 1);

    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);

    vector<int> p{paths + 1, paths + 1 + n};
    segTree = SegTree(p , 1 , n);

    //int x = pathQuerry(1 , 7);
    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);
        }
    }
    return 0;
}