Cod sursa(job #3123944)

Utilizator Chris_BlackBlaga Cristian Chris_Black Data 26 aprilie 2023 13:56:54
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.56 kb
#include <bits/stdc++.h>
#define VI vector<int>
#define VVI vector<VI>
#define PI pair<int,int>
#define PB push_back
using namespace std;
const int N = 1e5 + 9, Inf = 0x3f3f3f3f;
int cost[N],which[N],poz[N],t[N],dep[N],w[N];
int n,m,a,b,op,x,val;
VVI G;
VVI lanturi;
int tree[8*N + 1];
int root[N];
int NEXT_INDEX;

void Dfs(int x,int p)
{
    w[x] = 1;

    if(G[x].size() == 1 && dep[x] > 0)
    {
        which[x] = lanturi.size();
        poz[x] = 0;
        lanturi.PB(VI(1,x));
        return;
    }

    int maxz = -1;
    int nod = -1;
    for(auto y : G[x])
    {
        if(y == p)continue;

        t[y] = x;
        dep[y] = dep[x] + 1;
        Dfs(y, x);
        w[x] += w[y];

        if(w[y] > maxz)
        {
            maxz = w[y];
            nod = y;
        }

    }

    which[x] = which[nod];
    poz[x] = lanturi[which[nod]].size();
    lanturi[which[nod]].PB(x);
}

void build(int offset, int nod, int st, int dr, int idx)
{
    if(st == dr)
    {
        tree[nod + offset] = cost[lanturi[idx][st]];
        return;
    }
    int mij = (st + dr) >> 1;
    build(offset, nod<<1, st, mij, idx);
    build(offset, nod<<1|1, mij + 1, dr, idx);

    tree[nod + offset] = max(tree[(nod<<1) + offset], tree[(nod<<1|1) + offset]);
}

void update(int offset, int nod, int st,int dr,int poz, int val)
{
    if(st == dr)
    {
        tree[nod + offset] = val;
        return;
    }
    int mij = (st + dr)>>1;
    if(poz <= mij)
        update(offset, nod<<1, st, mij, poz, val);
    else
        update(offset, nod<<1|1, mij+1, dr, poz, val);

    tree[nod + offset] = max(tree[(nod<<1) + offset], tree[(nod<<1|1) + offset]);
}

int query(int offset, int nod, int st,int dr,int a, int b)
{
    if(a <= st && dr <= b)
        return tree[offset + nod];
    int mij = (st + dr)>>1;
    if(b <= mij)
        return query(offset, nod<<1, st, mij, a, b);
    else if(a > mij)
        return query(offset, nod<<1|1, mij + 1, dr, a, b);
    return max(query(offset, nod<<1, st, mij, a, b), query(offset, nod<<1|1, mij + 1, dr, a, b));
}

void Build()
{
    for(size_t i = 0; i < lanturi.size(); ++i)
    {
        root[i] = NEXT_INDEX;
        build(root[i], 1, 0, lanturi[i].size() - 1, i);
        NEXT_INDEX += 5 * lanturi[i].size();
    }
}

int query(int a,int b)
{
    if(a == b)return cost[a];

    int res = -Inf;
    for(; which[a] != which[b]; b = t[lanturi[which[b]][lanturi[which[b]].size() - 1]])
    {
        if(dep[lanturi[which[a]][lanturi[which[a]].size()-1]] > dep[lanturi[which[b]][lanturi[which[b]].size()-1]])
            swap(a, b);
        res = max(res, query(root[which[b]], 1, 0, lanturi[which[b]].size() - 1, poz[b], lanturi[which[b]].size() - 1));
    }

    if(a == b)return res;

    if(dep[a] < dep[b])
        swap(a, b);

    return max(res, query(root[which[a]], 1, 0, lanturi[which[a]].size() - 1, poz[a], poz[b]));
}

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

    cin>>n>>m;
    G = VVI(n+1);

    for(int i = 1; i <= n; ++i)
        cin>>cost[i];
    for(int i = 1; i < n; ++i)
    {
        cin>>a>>b;
        G[a].PB(b);
        G[b].PB(a);
    }

    Dfs(1, 0);
    Build();

    while(m--)
    {
        cin>>op;
        if(op == 0)
        {
            cin>>x>>val;
            update(root[which[x]], 1, 0, lanturi[which[x]].size() - 1, poz[x], val);
        }
        else
        {
            cin>>a>>b;
            cout<<query(a,b)<<'\n';
        }
    }
    return 0;
}