Cod sursa(job #1960533)

Utilizator Train1Train1 Train1 Data 10 aprilie 2017 14:54:06
Problema Heavy Path Decomposition Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 3.71 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#define NMax 100001
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
vector <int> v[NMax], lant[NMax], arbInt[NMax];
int w[NMax], label[NMax], pos[NMax], valori[NMax], roof[NMax], nivel[NMax], lantSize[NMax];
int n, m, x, y, op, labelNr = 1, posNr, VAL, R, POS, niv;
void DFS(int nod) {
    int fiu;
    w[nod] = 1;
    niv++;
    lant[labelNr].push_back(nod);
    label[nod] = labelNr;
    pos[nod] = posNr;
    posNr++;
    nivel[nod] = niv;
    bool leaf = true;
    int nodSize = v[nod].size();
    for(int i = 0 ; i < nodSize; ++i) {
        fiu = v[nod][i];
        if(label[fiu])
            continue;
        DFS(fiu);
        w[nod] += w[fiu];
        roof[labelNr] = nod;

        leaf = false;
        posNr = 0;
    }
    if(leaf) {
        lantSize[labelNr] = posNr;
        labelNr++;
    }
    niv--;
}
void update(int nod, int st, int dr) {
    if(st == dr) {
        arbInt[R][nod] = VAL;
    } else {
        int mij = (st + dr) / 2;
        if (POS <= mij) {
            update(2 * nod, st, mij);
        } else {
            update(2 * nod + 1, mij + 1, dr);
        }
        if(valori[arbInt[R][2* nod]] > valori[arbInt[R][2 * nod+ 1]]) {
            arbInt[R][nod] = arbInt[R][2 * nod];
        } else {
            arbInt[R][nod] = arbInt[R][2 * nod + 1];
        }
    }
}
void buildTree() {
    int rSize = lantSize[R];
    arbInt[R].resize(rSize * 4 + 1);
    for(int i = 0; i < rSize; ++i) {
        VAL = lant[R][i];
        POS = i + 1;
        update(1, 1, rSize);
    }
}
int posStart, posFinish, arbLant, maximV;
void arbQuery(int nod, int st, int dr) {
    if(st >= posStart && dr <= posFinish) {
        maximV = max(maximV, valori[arbInt[arbLant][nod]]);
        return;
    }
    int mid = (st + dr) / 2;
    if(posStart <= mid) arbQuery(2 * nod, st, mid);
    if(mid < posFinish) arbQuery(2 * nod + 1, mid + 1, dr);
}
int query(int x, int y) {
    maximV = -1;
    while(true) {
        if(label[x] == label[y]) {
            posStart = pos[x] + 1;
            posFinish = pos[y] + 1;
            if(posStart > posFinish) {
                int aux = posFinish;
                posFinish = posStart;
                posStart = aux;
            }
            arbLant = label[x];
            arbQuery(1, 1, lantSize[arbLant]);
            break;
        } else {
            int dadX = roof[label[x]];
            int dadY = roof[label[y]];
            if(nivel[dadX] > nivel[dadY]) {
                posStart = pos[1] + 1;
                posFinish = pos[x] + 1;
                arbLant = label[x];
                arbQuery(1, 1, lantSize[arbLant]);
                x = dadX;
            } else {
                posStart = pos[1] + 1;
                posFinish = pos[y] + 1;
                arbLant = label[y];
                arbQuery(1, 1, lantSize[arbLant]);
                y = dadY;
            }
        }
    }
    //cout<<'\n';
    fout<<maximV<<'\n';
}
int main()
{
    fin>>n>>m;
    for(int i = 1; i <= n; ++i) {
        fin>>valori[i];
    }
    for(int i = 1; i < n; ++i) {
        fin>>x>>y;
        v[x].push_back(y);
        v[y].push_back(x);
    }
    DFS(1);
    for(int i = 1 ; i <= labelNr; ++i) {
        R = i;
        buildTree();
    }

    for(int i = 1; i <= m; ++i) {
        fin>>op>>x>>y;
        if(op == 1) {
            query(x, y);
        } else {
            valori[x] = y;
            R = label[x];
            VAL = lant[R][pos[x]];
            POS = pos[x] + 1;
            update(1, 1, lantSize[R]);
        }
    }
    fin.close();
    fout.close();
    return 0;
}