Cod sursa(job #2986801)

Utilizator Andrei_ierdnANeculau Rares-Andrei Andrei_ierdnA Data 1 martie 2023 11:17:46
Problema Heavy Path Decomposition Scor 60
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.9 kb
#include <bits/stdc++.h>

using namespace std;

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

#define int long long

int n, m, i, j, v[100100], a, b, t, normn, lca;
vector<int> neighbours[100100];
int heavychild[100100], tsize[100100], p[100100];
int pathroot[100100], poz[100100], depth[100100];
int segtree[280100], dsu[100100];
vector<pair<int, int>> lcaquery[100100];
bool viz[100100];

struct query
{
    int t, x, y;
} queries[100100];

int dsuGetRoot(int node)
{
    if (!dsu[node])
        return node;
    return dsu[node] = dsuGetRoot(dsu[node]);
}

void dfs1(int node, int parent)
{
    tsize[node] = 1;
    p[node] = parent;
    for (int j = 0; j < neighbours[node].size(); j++) {
        if (neighbours[node][j] != parent) {
            depth[neighbours[node][j]] = depth[node] + 1;
            dfs1(neighbours[node][j], node);
            tsize[node] += tsize[neighbours[node][j]];
            if (tsize[neighbours[node][j]] > tsize[heavychild[node]]) {
                heavychild[node] = neighbours[node][j];
            }
        }
    }
}

void heavyfirst(int node, int parent)
{
    poz[node] = ++t;
    segtree[normn + t - 1] = v[node];
    if (heavychild[node]) {
        pathroot[heavychild[node]] = pathroot[node];
        heavyfirst(heavychild[node], node);
        for (int j = 0; j < neighbours[node].size(); j++) {
            if (neighbours[node][j] != parent && neighbours[node][j] != heavychild[node]) {
                pathroot[neighbours[node][j]] = neighbours[node][j];
                heavyfirst(neighbours[node][j], node);
            }
        }
    }
}

void tarjandfs(int node)
{
    viz[node] = true;
    for (int j = 0; j < lcaquery[node].size(); j++) {
        if (viz[lcaquery[node][j].first]) {
            lcaquery[node][j].second = dsuGetRoot(lcaquery[node][j].first);
        }
    }
    for (int j = 0; j < neighbours[node].size(); j++) {
        if (!viz[neighbours[node][j]]) {
            tarjandfs(neighbours[node][j]);
            dsu[neighbours[node][j]] = node;
        }
    }
}

int segtreeQuery(int st, int dr)
{
    int ans = 0;
    st = normn + st - 1;
    dr = normn + dr - 1;
    while (st < dr) {
        if ((st & 1) == 1) {
            ans = max(ans, segtree[st++]);
        }
        if ((dr & 1) == 0) {
            ans = max(ans, segtree[dr--]);
        }
        st >>= 1;
        dr >>= 1;
    }
    if (st == dr)
        ans = max(ans, segtree[st]);
    return ans;
}


#undef int

int main()
{
    f >> n >> m;
    for (i = 1; i <= n; i++) {
        f >> v[i];
    }
    normn = n;
    while (normn & (normn-1)) {
        normn = normn + (normn & (-normn));
    }
    for (i = 1; i < n; i++) {
        f >> a >> b;
        neighbours[a].push_back(b);
        neighbours[b].push_back(a);
    }
    depth[1] = 1;
    dfs1(1, 0);
    pathroot[1] = 1;
    heavyfirst(1, 0);
    for (i = normn - 1; i >= 1; i--) {
        segtree[i] = max(segtree[2*i], segtree[2*i+1]);
    }
    for (i = 1; i <= m; i++) {
        f >> queries[i].t >> queries[i].x >> queries[i].y;
    }
    for (i = m; i >= 1; i--) {
        if (queries[i].t == 1) {
            lcaquery[queries[i].x].push_back({queries[i].y, 0});
            lcaquery[queries[i].y].push_back({queries[i].x, 0});
        }
    }
    tarjandfs(1);
    for (i = 1; i <= m; i++) {
        if (queries[i].t == 0) {
            j = normn + poz[queries[i].x] - 1;
            segtree[j] = queries[i].y;
            j >>= 1;
            while (j) {
                segtree[j] = max(segtree[2*j], segtree[2*j+1]);
                j >>= 1;
            }
        }
        else if (queries[i].t == 1) {
            long long rasp = 0;
            lca = max(lcaquery[queries[i].x].back().second, lcaquery[queries[i].y].back().second);
            lcaquery[queries[i].x].pop_back();
            lcaquery[queries[i].y].pop_back();
            long long node = queries[i].x;
            while (node) {
                long long head = pathroot[node];
                if (depth[head] > depth[lca]) {
                    rasp = max(rasp, segtreeQuery(poz[head], poz[node]));
                    node = p[head];
                }
                else {
                    rasp = max(rasp, segtreeQuery(poz[lca], poz[node]));
                    node = 0;
                }
            }
            node = queries[i].y;
            while (node) {
                long long head = pathroot[node];
                if (depth[head] > depth[lca]) {
                    rasp = max(rasp, segtreeQuery(poz[head], poz[node]));
                    node = p[head];
                }
                else {
                    rasp = max(rasp, segtreeQuery(poz[lca], poz[node]));
                    node = 0;
                }
            }
            g << rasp << '\n';
        }
    }
    f.close();
    g.close();
    return 0;
}