Cod sursa(job #1960843)

Utilizator Train1Train1 Train1 Data 10 aprilie 2017 18:38:10
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.14 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], father[NMax];
int n, m, x, y, op, labelNr = 1, posNr, VAL, R, POS, niv;
void DFS(int nod, int Tnod) {
    int fiu, maxSon = 0;
    w[nod] = 1;
    nivel[nod] = nivel[Tnod] + 1;
    int nodSize = v[nod].size();
    bool leaf = true;
    for(int i = 0; i < nodSize; i++) {
        fiu = v[nod][i];
        if(fiu == Tnod)
            continue;
        leaf = false;
        father[fiu] = nod;
        DFS(fiu, nod);
        w[nod]+=w[fiu];
        if(w[maxSon] < w[fiu]) {
            maxSon = fiu;
        }
    }
    if(leaf) {
        lant[labelNr].push_back(0);
        lant[labelNr].push_back(nod);
        label[nod] = labelNr;
        pos[nod] = 1;
        labelNr++;
    } else {
        label[nod] = label[maxSon];
        pos[nod] = pos[maxSon] + 1;
        lant[label[nod]].push_back(nod);
    }
}
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 = lant[R].size();
    reverse(lant[R].begin() + 1, lant[R].end());
    roof[R] = father[lant[R][1]];
    arbInt[R].resize(rSize * 4 + 1);
    for(int i = 1; i < rSize; ++i) {
        VAL = lant[R][i];
        POS = i;
        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];
            posFinish = pos[y];
            if(posStart > posFinish) {
                int aux = posFinish;
                posFinish = posStart;
                posStart = aux;
            }
            arbLant = label[x];
            arbQuery(1, 1, lant[arbLant].size());
            break;
        } else {
            int dadX = roof[label[x]];
            int dadY = roof[label[y]];
            if(nivel[dadX] > nivel[dadY]) {
                posStart = pos[1];
                posFinish = pos[x];
                arbLant = label[x];
                //cout<<posStart<<' '<<posFinish<<' '<<arbLant<<'\n';
                arbQuery(1, 1, lant[arbLant].size());
                x = dadX;
            } else {
                posStart = pos[1];
                posFinish = pos[y];
                arbLant = label[y];
                arbQuery(1, 1, lant[arbLant].size());
                y = dadY;
            }
        }
    }
    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, 0);
    labelNr--;
    for(int i = 1; i <= n; ++i) {
        pos[i] = lant[label[i]].size() - pos[i];
        cout<<pos[i]<<' ';
    }
    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];
            update(1, 1, lant[R].size());
        }
    }
    fin.close();
    fout.close();
    return 0;
}