Cod sursa(job #1213159)

Utilizator mariusn01Marius Nicoli mariusn01 Data 27 iulie 2014 14:18:07
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.51 kb
#include <fstream>
#include <iostream>
#include <vector>
#include <bitset>

#define DIM 100010
#define INF 2000000010

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

vector<int> L[DIM];     //lista de vecini
vector<int> Lant[DIM];  //Lant[i] = nodurile din lantul i
int nrLant[DIM];        //nrLant[i] = numarul lantului in care e nodul i
int N[DIM];             //N[i] = nivelul nodului i
int T[DIM];             //T[i] = tatal lantului i (nod care nu e in lantul i)
int Tata[DIM];          //Tata[i] = tatal nodului i in arbore
int P[DIM];             //P[i] = pozitia nodului i in lantul sau
int Start[DIM];         //Start[i] = pozitia la care incepe lantul i in arborele de intervale
int Desc[DIM];          //Desc[i] = numarul de noduri din subarborele lui i
bitset<DIM> U;
int A[4*DIM];
int V[DIM];

int nrLanturi;  //numarul total de lanturi
int n, m, i, j, l1, l2, q, x, y, k, t, a, b, maxim;

void dfs(int nod, int niv, int tata) {
    N[nod] = niv;
    U[nod] = 1;
    Desc[nod] = 1;
    Tata[nod] = tata;
    int maximDesc = 0;
    int fiuMaximDesc;
    for (int i=0;i<L[nod].size();i++) {
        int fiu = L[nod][i];
        if (!U[fiu]) {
            dfs(fiu, niv+1, nod);
            Desc[nod] += Desc[fiu];
            //Tata[fiu] = nod;
            if (Desc[fiu] > maximDesc) {
                maximDesc = Desc[fiu];
                fiuMaximDesc = fiu;
            }
        }
    }

    if (maximDesc == 0) {
        Lant[++nrLanturi].push_back(nod);
        nrLant[nod] = nrLanturi;
        T[nrLanturi] = Tata[nod];

    } else {
        Lant[nrLant[fiuMaximDesc]].push_back(nod);
        nrLant[nod] = nrLant[fiuMaximDesc];
        T[nrLant[fiuMaximDesc]] = Tata[nod];
    }

}

void swap(int &a, int &b) {
    int aux = a;
    a = b;
    b = aux;
}

void update(int nod, int st, int dr, int p, int x, int decalaj) {
    //A[nod + decalaj] este maximul informatiilor nodurilor aflate intre
    //pozitiile st si dr in lantul Lant[lant] si care in arborele de

    if (st == dr) {
        A[nod+decalaj] = x;
        return;
    }

    int mid = (st+dr)/2;
    if (p<=mid)
        update(2*nod, st, mid, p, x, decalaj);
    if (p>mid)
        update(2*nod+1, mid+1, dr, p, x, decalaj);
    A[nod+decalaj] = max(A[2*nod+decalaj], A[2*nod+1+decalaj]);
}

int query(int nod, int st, int dr, int a, int b, int decalaj) {
    if (a<=st && dr<=b)
        return A[nod+decalaj];
    int mid = (st + dr)/2;
    int qst = 0, qdr=0;
    if (a <= mid)
        qst = query(2*nod, st, mid, a, b, decalaj);
    if (b > mid)
        qdr = query(2*nod+1, mid+1, dr, a, b, decalaj);
    return max(qst, qdr);
}

int main() {
    fin>>n>>q;
    for (i=1;i<=n;i++)
        fin>>V[i];
    for (i=1;i<n;i++) {
        fin>>x>>y;
        L[x].push_back(y);
        L[y].push_back(x);
    }

    dfs(1,1,0);

    // sortez crescator dupa nivel nodurile din acelasi lant

    for (i=1;i<=nrLanturi;i++) {
        Start[i] = Start[i-1] + 4*Lant[i-1].size();
        for (j=0,k=Lant[i].size()-1;j<k;j++,k--) {
            swap(Lant[i][j], Lant[i][k]);
            P[Lant[i][j]] = j;
            P[Lant[i][k]] = k;
        }
        P[Lant[i][j]] = j;
    }

    for (i=1;i<=nrLanturi;i++) {
        for (j=0;j<Lant[i].size();j++) {
            cout<<Lant[i][j]<<" ";
        }
        cout<<"\n";
    }

    for (i=1;i<=n;i++) {
        update(1, 0, Lant[  nrLant[  i  ] ].size()-1, P[i], V[i], Start[  nrLant[  i  ] ]   );
    }

    for (;q--;) {
        fin>>t>>a>>b;
        if (t == 0) {
            //V[a] = b;
            update(1, 0, Lant[  nrLant[  a  ] ].size()-1, P[a], b, Start[  nrLant[  a  ] ]   );
        } else {
            //maximul de pe drumul dintre nodurile a si b
            maxim = 0;
            do {
                l1 = nrLant[a];
                l2 = nrLant[b];

                if (l1 == l2) {
                    maxim = max(maxim, query(1, 0, Lant[  l1 ].size()-1, min( P[a], P[b]  ), max(P[a], P[b]), Start[l1] ) );
                    break;
                }
                if (  N[T[l1]] > N[ T[l2] ]  ) {
                    maxim = max(maxim, query(1, 0, Lant[  l1 ].size()-1, 0, P[a], Start[l1] ) );
                    a = T[l1];
                } else {
                    maxim = max(maxim, query(1, 0, Lant[  l2 ].size()-1, 0, P[b], Start[l2] ) );
                    b = T[l2];
                }
            } while (1);
            fout<<maxim<<"\n";
        }
    }
    return 0;
}