Cod sursa(job #2985995)

Utilizator LuciBBadea Lucian LuciB Data 27 februarie 2023 15:28:06
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.8 kb
#include <bits/stdc++.h>

using namespace std;

const int NMAX = 1e5;

int n;
vector<int> graph[NMAX];

int aint[2 * NMAX];
int heavy[NMAX];
int head[NMAX];
int parent[NMAX];
int depth[NMAX];
int euler[NMAX];

int v[NMAX];

int aint_join(int a, int b) {
    return (a > b ? a : b);
}

void aint_update(int node, int left, int right, int poz, int val) {
    if(left == right) {
        aint[node] = val;
    } else {
        int leftChild, rightChild, mid;
        mid = (left + right) / 2;
        leftChild = node + 1;
        rightChild = node + 2 * (mid - left + 1);
        if(poz <= mid)
            aint_update(leftChild, left, mid, poz, val);
        else
            aint_update(rightChild, mid + 1, right, poz, val);
        aint[node] = aint_join(aint[leftChild], aint[rightChild]);
    }
}

int aint_query(int node, int left, int right, int qLeft, int qRight) {
    int leftChild, rightChild, mid;
    mid = (left + right) / 2;
    leftChild = node + 1;
    rightChild = node + 2 * (mid - left + 1);
    if(left == qLeft && right == qRight)
        return aint[node];
    else {
        if(qRight <= mid)
            return aint_query(leftChild, left, mid, qLeft, qRight);
        if(qLeft > mid)
            return aint_query(rightChild, mid + 1, right, qLeft, qRight);
        return aint_join(aint_query(leftChild, left, mid, qLeft, mid),
                         aint_query(rightChild, mid + 1, right, mid + 1, qRight));
    }
}

int dfs(int node, int nodeParent = -1) {
    int maxSize = 0, size = 1;
    parent[node] = nodeParent;
    heavy[node] = -1;
    for(auto neighbour : graph[node]) {
        if(neighbour != nodeParent) {
            depth[neighbour] = depth[node] + 1;
            int neighbourSize = dfs(neighbour, node);
            size += neighbourSize;
            if(neighbourSize > maxSize) {
                maxSize = neighbourSize;
                heavy[node] = neighbour;
            }
        }
    }
    return size;
}

int eulerTime;

void decompose(int node, int nodeParent, int nodeHead) {
    head[node] = nodeHead;
    euler[node] = eulerTime++;
    if(heavy[node] != -1) // not leaf
        decompose(heavy[node], node, nodeHead);
    for(auto neighbour : graph[node]) {
        if(neighbour != nodeParent && neighbour != heavy[node])
            decompose(neighbour, node, neighbour);
    }
}

void heavy_update(int node, int val) {
    aint_update(0, 0, n - 1, euler[node], val);
}

int heavy_query(int a, int b) {
    int ans = 0;
    while(head[a] != head[b]) {
        if(depth[head[a]] < depth[head[b]])
            swap(a, b);
        ans = max(ans, aint_query(0, 0, n - 1, euler[head[a]], euler[a]));
        a = parent[head[a]];
    }
    ans = max(ans, aint_query(0, 0, n - 1, min(euler[a], euler[b]), max(euler[a], euler[b])));
    return ans;
}

int main() {
    int q;
    FILE *fin, *fout;
    fin = fopen("heavypath.in", "r");
    fout = fopen("heavypath.out", "w");
    fscanf(fin, "%d%d", &n, &q);
    for(int i = 0; i < n; i++)
        fscanf(fin, "%d", &v[i]);
    for(int i = 0; i < n - 1; i++) {
        int a, b;
        fscanf(fin, "%d%d", &a, &b);
        a--;
        b--;
        graph[a].push_back(b);
        graph[b].push_back(a);
    }
    dfs(0);
    eulerTime = 0;
    decompose(0, -1, 0);
    /*for(int i = 0; i < n; i++) {
        cout << "Node: " << i + 1 << " heavy: " << heavy[i] + 1<< '\n';
    }
    cout << endl;
    for(int i = 0; i < n; i++) {
        cout << "Node: " << i + 1 << " head: " << head[i] + 1 << '\n';
    }
    cout << endl;*/
    for(int i = 0; i < n; i++)
        heavy_update(i, v[i]);
    for(int i = 0; i < q; i++) {
        int a, b, c;
        fscanf(fin, "%d%d%d", &a, &b, &c);
        if(a == 0) {
            heavy_update(b - 1, c);
        } else {
            fprintf(fout, "%d\n", heavy_query(b - 1, c - 1));
        }
    }
    fclose(fin);
    fclose(fout);
    return 0;
}