Cod sursa(job #2966919)

Utilizator raulandreipopRaul-Andrei Pop raulandreipop Data 18 ianuarie 2023 18:02:49
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 6.09 kb
#include <iostream>
#include <vector>

#define aintNull 0
#define aintData int

using namespace std;



struct AINT {
    int offset;
  //  int n;
    vector<int> aint;

    aintData merge (aintData a, aintData b)
    {
        aintData par;
        par = max(a, b);
        return par;
    }

    void build (int nod, int l, int r, vector<aintData>& a)
    {
        if (l >= a.size()) return;
        if (l == r){
            aint[nod] = a[l];
            return;
        }
        int m = (l + r) / 2;
        build(2 * nod, l, m, a);
        build(2 * nod + 1, m + 1, r, a);
        aint[nod] = merge(aint[2 * nod], aint[2 * nod + 1]);
    }

    void buildLin (vector<aintData>& a)
    {
        for (int i = offset; i < 2 * offset; i++)
        {
            aint[i] = a[i - offset + 1];
        }
        for (int i = offset - 1; i > 0; i--)
        {
            aint[i] = merge(aint[2 * i], aint[2 * i + 1]);
        }
    }
    
    void initialize(int n, vector<aintData>& a)
    {
        offset = 1;
        while (offset < n) offset *= 2;
        aint.resize(2 * offset + 1);
        buildLin(a);
    }

    void upd (int nod, int l, int r, int pos, int val)
    {
        if (l == r)
        {
            if (l == pos) {
                aint[nod] = val;
            }
            return;
        }
        if (l > pos || r < pos) return;
        
        int m = (l + r) / 2;
        if (m >= pos) upd(2 * nod, l, m, pos, val);
        else upd(2 * nod + 1, m + 1, r, pos, val);
        aint[nod] = merge(aint[2 * nod], aint[2 * nod + 1]);
    }

    void updLin (int pos, int val)
    {
        int updPos = pos + offset - 1;
        aint[updPos] = val;
        updPos /= 2;
        while (updPos > 0)
        {
            aint[updPos] = merge(aint[2 * updPos], aint[2 * updPos + 1]);
            updPos /= 2;
        }
    }

    void update (int pos, int val)
    {
      //  upd(1, 1, offset, pos, val);
        updLin(pos, val);
    }

    aintData qry (int nod, int l, int r, int ql, int qr)
    {
        if (ql <= l && r <= qr)
        {
            return aint[nod];
        }
        if (r < ql || l > qr) return aintNull;
        int m = (l + r) / 2;
        return merge(qry(2 * nod, l, m, ql, qr), 
        qry(2 * nod + 1, m + 1, r, ql, qr));
    }

    aintData query(int l, int r)
    {
        return qry(1, 1, offset, l, r);
    }

};

const int nmax = 1e5 + 9;
int v[nmax];
int p[nmax];

struct HLD {
    vector<int> adj[nmax];
    AINT aint;
    int n;
    int subtree[nmax];
    int heavyChild[nmax];
    vector<int> heavyOrder;
    int heavyHead[nmax];
    int depth[nmax];
    int parent[nmax];
    int revOrder[nmax];

    void calcSubtree (int nod = 1, int par = 0)
    {
        parent[nod] = par;
        subtree[nod] = 1;
        depth[nod] = depth[par] + 1;
        int maxSon = 0, sonInd = -1;
        for (int to : adj[nod])
        {
            if (to == par) continue;
            calcSubtree(to , nod);
            subtree[nod] += subtree[to];
            if (subtree[to] > maxSon)
            {
                maxSon = subtree[to];
                sonInd = to;
            }
        }
        heavyChild[nod] = sonInd;
    }

    void heavyFirst (int nod, int par, int head)
    {
        heavyHead[nod] = head;
        heavyOrder.push_back(nod);
        revOrder[nod] = heavyOrder.size() - 1;
        if (heavyChild[nod] != -1) heavyFirst(heavyChild[nod] , nod, head);
        for (auto to : adj[nod])
        {
            if (to != heavyChild[nod] && to != par)
            {
                heavyFirst(to , nod, to);
            }
        }
    }
    void printHeavyOrder ()
    {
        for (int i = 1; i <= n; i++)
        {
            cout << heavyOrder[i] << ' ';
        }
        for (int i = 1; i <= n; i++)
        {
            cout << i << ' ' << revOrder[i] << '\n';
        }
        cout << '\n';
    }
    
    void initialize(int N)
    {
        n = N;
        heavyOrder.push_back(0);
   
        calcSubtree();
        heavyFirst(1, 0, 1);

        vector<int> a;
        a.push_back(0);
        
        for (int i = 1; i <= n; i++)
        {
            a.push_back(v[heavyOrder[i]]);
           
        }
        
        aint.initialize(n, a);
    }

    int lca (int u, int v)
    {
        if (heavyHead[u] == heavyHead[v]) {
            if (depth[u] < depth[v]) return u;
            else return v;
        }
        if (depth[heavyHead[u]] < depth[heavyHead[v]])
        {
            return lca(parent[heavyHead[v]] , u);
        }
        else {
            return lca(parent[heavyHead[u]] , v);
        }
    }

    int queryMax (int u, int v)
    {
        if (heavyHead[u] == heavyHead[v]) {
            if (depth[u] < depth[v]) return aint.query(revOrder[u] , revOrder[v]);
            else return aint.query(revOrder[v] , revOrder[u]);
        }
        if (depth[heavyHead[u]] < depth[heavyHead[v]])
        {
            return max(aint.query(revOrder[heavyHead[v]] , revOrder[v])
            , queryMax(parent[heavyHead[v]] , u));
        }
        else {
            return max(aint.query(revOrder[heavyHead[u]] , revOrder[u])
            , queryMax(parent[heavyHead[u]] , v));
        }
    }

    int query (int u, int v)
    {
        return queryMax(u, v);
    }
    int update (int u, int val)
    {
        aint.update(revOrder[u] , val);
    }
};

int main ()
{
    freopen("heavypath.in" , "r" , stdin);
    freopen("heavypath.out" , "w" , stdout);

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

    HLD hld;
    for (int i = 1; i < n; i++)
    {
        int x, y; cin >> x >> y;
        hld.adj[x].push_back(y);
        hld.adj[y].push_back(x);
    }
    hld.initialize(n);
 //   hld.printHeavyOrder();
    while (q--)
    {
        int t , x, y; cin >> t >> x >> y;
        if (t == 0) {
            hld.update(x, y);
        }
        else {
            cout << hld.query(x, y) << '\n';
        }
    }
}