Cod sursa(job #3364427)

Utilizator Andrei-Dani-10Pisla Andrei Daniel Andrei-Dani-10 Data 3 septembrie 2026 12:44:56
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.33 kb
#include <fstream>

#include <vector>
#pragma GCC optimize("O3")

#include <algorithm>

using namespace std;

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

const int nmax = 1e5, max32_t = (1 << 30);
int n, nrq, a[nmax + 2], typee, xx, yy;

vector <int> edges[nmax + 2];

struct segmenttree{
    int tree[4 * nmax + 2];

    void build(int node, int st, int dr){
        if(st != dr){
            int mij = (st + dr) >> 1;
            build((node << 1), st, mij);
            build((node << 1) | 1, mij + 1, dr);
        }; tree[node] = -max32_t; return;
    }
    
    void update(int node, int st, int dr, int idx, int valuee){
        if(st == dr){
            tree[node] = valuee;
        }else{
            int mij = (st + dr) >> 1;
            if(idx <= mij) update((node << 1), st, mij, idx, valuee);
            if(mij < idx) update((node << 1) | 1, mij + 1, dr, idx, valuee);
            tree[node] = max(tree[(node << 1)], tree[(node << 1) | 1]);
        }; return;
    }

    int query(int node, int st, int dr, int leftt, int rightt){
        if(leftt <= st && dr <= rightt){
            return tree[node];
        }else{
            int mij = (st + dr) >> 1, qry = -max32_t;
            if(leftt <= mij) qry = max(qry, query((node << 1), st, mij, leftt, rightt));
            if(mij < rightt) qry = max(qry, query((node << 1) | 1, mij + 1, dr, leftt, rightt));
            return qry;
        }; return -max32_t;
    }

    int _query(int leftt, int rightt){
        if(leftt > rightt){ swap(leftt, rightt); }
        return query(1, 1, n, leftt, rightt);
    }
} segtree;

struct heavylightdecomposition{

    int subtreesz[nmax + 2], depth[nmax + 2], father[nmax + 2];
    int headpath[nmax + 2], whatchain[nmax + 2];

    int hldtag[nmax + 2]; vector <int> chainnodes[nmax + 2];

    void dfsbuild(int node, int parent){
        subtreesz[node] = 1; father[node] = parent;
        depth[node] = depth[parent] + 1;

        int heavykiddo = 0;

        for(auto nxt : edges[node]){
            if(nxt == parent){ continue; }
        
            dfsbuild(nxt, node);
            subtreesz[node] += subtreesz[nxt];
            
            /// get the chain from the biggest subtree ///
            if(subtreesz[heavykiddo] < subtreesz[nxt]){
                heavykiddo = nxt;
            }
        }

        /// create / append to a chain ///
        if(!heavykiddo) whatchain[heavykiddo]++;
        whatchain[node] = whatchain[heavykiddo];

        headpath[whatchain[node]] = node;

        chainnodes[whatchain[node]].push_back(node);

        return;
    }

    /// helper function ///
    inline int getheadpath(int node){
        return headpath[whatchain[node]];
    }

    void build(){
        dfsbuild(1, 0); segtree.build(1, 1, n);

        /// O(n) additional memory instead of another dfs ///
        for(int i = 1, tag = 0; i <= whatchain[0]; i++){
            reverse(chainnodes[i].begin(), chainnodes[i].end()); /// necessary
            for(auto &xx : chainnodes[i]){ 
                hldtag[xx] = (++tag); segtree.update(1, 1, n, hldtag[xx], a[xx]);
            }
        }

        // for(int i = 1; i <= n; i++){
        //     out<<i<<" -> "<<whatchain[i]<<" | "<<getheadpath(i)<<" - "<<hldtag[i]<<"\n";
        // }

        return;
    }

    /// answer queries and updates ///
    void update(int xx, int yy){ 
        a[xx] = yy; /// change a[xx] = yy
        segtree.update(1, 1, n, hldtag[xx], a[xx]);

        return;
    }

    int query(int xx, int yy){ /// get max on path from xx to yy
        int maxonpath = -max32_t;

        for(; getheadpath(xx) != getheadpath(yy); ){
            if(depth[getheadpath(xx)] < depth[getheadpath(yy)]){ swap(xx, yy); }
        
            maxonpath = max(maxonpath, segtree._query(hldtag[xx], hldtag[getheadpath(xx)]));
            xx = father[getheadpath(xx)];
        }

        maxonpath = max(maxonpath, segtree._query(hldtag[xx], hldtag[yy]));

        return maxonpath;
    }
} hld;

int main(){

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

    for(int i = 1; i <= n - 1; i++){
        in>>xx>>yy;
        edges[xx].push_back(yy);
        edges[yy].push_back(xx);
    }

    hld.build();

    for(int itq = 1; itq <= nrq; itq++){
        in>>typee>>xx>>yy;

        if(typee == 0){
            hld.update(xx, yy);
        }else{
            out<<hld.query(xx, yy)<<"\n";
        }
    }

    return 0;
}