Cod sursa(job #2765291)

Utilizator NeacsuMihaiNeacsu Mihai NeacsuMihai Data 26 iulie 2021 11:01:13
Problema Heavy Path Decomposition Scor 50
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.77 kb
/*
    Am schimbat la linia 225
*/
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>

#define NMAX 100000 //o suta de mii

using namespace std;

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

int N, M;
int lantGlobal;

int **tree;

int val[NMAX + 1];
int weight[NMAX + 1];
int fiu_mx[NMAX + 1];
int dim[NMAX + 1];
int tataLant[NMAX + 1];
int pozLant[NMAX + 1];
int lantID[NMAX + 1];
int tt[NMAX + 1];
int height[NMAX + 1];

vector <int> G[NMAX + 1];

void precalculareOne(int node, int tata){
    /*
        weight[] si fiu_mx[]
    */
    tt[node] = tata;
    weight[node] = 1;
    height[node] = height[tata] + 1;

    for(int i = 0; i < G[node].size(); i++){
        int vec = G[node][i];

        if(vec != tata){
            precalculareOne(vec, node);

            if(weight[vec] > weight[ fiu_mx[node] ]){
                fiu_mx[node] = vec;
            }

            weight[node] += weight[vec];
        }
    }
}

void precalculareTwo(int node, int tata){
    dim[lantGlobal]++;

    if(dim[lantGlobal] == 1){
        tataLant[lantGlobal] = node;
    }
    pozLant[node] = dim[lantGlobal];
    lantID[node] = lantGlobal;

    /*
        Daca e frunza, return
        altfel, continui in fii
    */
    if(weight[node] == 1){
        return; //frunza
    }

    precalculareTwo(fiu_mx[node], node);

    for(int i = 0; i < G[node].size(); i++){
        int vec = G[node][i];

        if(vec != tata && vec != fiu_mx[node]){
            lantGlobal++;
            precalculareTwo(vec, node);
        }
    }
}

int IDTree;
int pozUpdate;
int valUpdate;
void updateTree(int node, int left, int right){
    if(left == right){
        tree[IDTree][node] = valUpdate;
        return;
    }

    int mid = left + (right - left) / 2;

    if(pozUpdate <= mid){
        updateTree(node * 2, left, mid);
    }
    else {
        updateTree(node * 2 + 1, mid + 1, right);
    }

    tree[IDTree][node] = max(tree[IDTree][node * 2], tree[IDTree][node * 2 + 1]);
}

void updateTreeUse(int ID, int poz, int val){
    IDTree = ID;
    pozUpdate = poz;
    valUpdate = val;

    updateTree(1, 1, dim[ID]);
}

int A, B; //IDTree e deja declarat mai sus
int queryTree(int node, int left, int right){
    if(A <= left && right <= B){
        return tree[IDTree][node];
    }

    int mid = left + (right - left) / 2;

    int rez1 = -1, rez2 = -1;
    if(A <= mid){
        rez1 = queryTree(node * 2, left, mid);
    }
    if(B >= mid + 1){
        rez2 = queryTree(node * 2 + 1, mid + 1, right);
    }

    return max(rez1, rez2);
}

int queryTreeUse(int ID, int st, int dr){
    if(st > dr){
        swap(st, dr);
    }

    IDTree = ID;
    A = st;
    B = dr;
    return queryTree(1, 1, dim[ID]);
}

int query(int x, int y){
    /*
        o functie de divide et impera

        mai intai tratez cazul de baza, cand se afla in acelasi lant
    */
    if(lantID[x] == lantID[y]){
        return queryTreeUse(lantID[x], pozLant[x], pozLant[y]);
    }

    if(height[ lantID[x] ] > height[ lantID[y] ]){
        swap(x, y);
    }
    //presupun ca lantul lui y incepe mai jos de lantul lui x
    int rez1 = query(y, tataLant[ lantID[y] ]);
    int rez2 = query(x, tt[ tataLant[ lantID[y] ] ]);

    return max(rez1, rez2);
}

void alocareDinamicaTree(){
    tree = (int **) malloc( (lantGlobal + 1) * sizeof(int *) );

    for(int i = 1; i <= lantGlobal; i++){
        tree[i] = (int *) malloc( (4 * dim[i] + 1) * sizeof(int) );
        for(int j = 0; j <= 4 * dim[i]; j++){
            tree[i][j] = 0;
        }
    }
}

void buildTree(){
    for(int i = 1; i <= N; i++){
        updateTreeUse(lantID[i], pozLant[i], val[i]);
    }
}

int main()
{
    fin >> N >> M;

    for(int i = 1; i <= N; i++){
        fin >> val[i];
    }

    for(int i = 1; i <= N - 1; i++){
        int x, y;
        fin >> x >> y;

        G[x].push_back(y);
        G[y].push_back(x);
    }

    precalculareOne(1, 1);
    lantGlobal = 1;
    precalculareTwo(1, 1);

    alocareDinamicaTree();
    buildTree();

    /*
    for(int i = 1; i <= N; i++){
        printf("%d apartine lantului %d\n", i, lantID[i]);
    }
    printf("\n");
    for(int i = 1; i <= lantGlobal; i++){
        printf("dim[ %d ] = %d\n", i, dim[i]);
    }
    printf("\n");
    for(int i = 1; i <= N; i++){
        printf("pozLant[ %d ] = %d\n", i, pozLant[i]);
    }
    printf("\n");
    */


    for(int i = 1; i <= M; i++){
        int tip, x, y;
        fin >> tip >> x >> y;

        if(tip == 0){
            updateTreeUse(lantID[x], pozLant[x], y);
        }
        else {
            fout << query(x, y) << "\n";
        }
    }

    return 0;
}