Cod sursa(job #2193532)

Utilizator MihaelaCismaruMihaela Cismaru MihaelaCismaru Data 10 aprilie 2018 14:29:36
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.83 kb
#include<fstream>
#include<vector>
#include<algorithm>

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

//variabile
const int dim = 100005;
int level[dim],hz[dim],lant[dim],nod_tata[dim],valoare[dim],poz[dim];
vector<int>v[dim],aint[dim],start[dim];
int l,n,q,a,b,t,x,y;
// functie pentru sortare
bool cmp (int a, int b) {
    return level[a] < level[b];
}
// dfs
int dfs (int nod, int nivel) {
    int noduri  = 0, maxim = 0,alfa = 0,ok = 0;
    hz[nod] = 1;
    level[nod] = nivel;
    for (int i = 0; i < v[nod].size(); i ++) {
        int vec = v[nod][i];
        if (hz[vec] == 1)
            continue;
        ok = 1;
        int vn = dfs (vec,nivel+1);
        noduri += vn;
        if (maxim < vn) {
            maxim = vn;
            alfa = vec;
        }
    }
    if (ok == 0) {
        start[++l].push_back (nod);
        lant[nod] = l;
        return 1;
    }
    start[lant[alfa]].push_back (nod);
    lant[nod] = lant[alfa];
    for (int i = 0; i < v[nod].size(); i ++) {
        if (level[v[nod][i]] < level[nod] || lant[v[nod][i]] == lant[nod])
            continue;
        nod_tata[lant[v[nod][i]]] = nod;
    }
    return noduri+1;
}
// operatii aint
void build (int nod,int st, int dr, int ind) {
    if (st == dr) {
        aint[ind][nod] = valoare[start[ind][st-1]];
        return;
    }
    int mid = (st + dr) >> 1;
    build (nod<<1,st,mid,ind);
    build (nod<<1|1,mid+1,dr,ind);
    aint[ind][nod] = max (aint[ind][nod<<1], aint[ind][nod<<1|1]);
    return;
}
void update (int nod, int st, int dr, int ind, int poz, int val) {
    if (st > poz || dr < poz) {
        return;
    }
    if (st == dr) {
        aint[ind][nod] = val;
        return;
    }
    int mid = (st + dr) >> 1;
    update (nod<<1,st,mid,ind,poz,val);
    update (nod<<1|1,mid+1,dr,ind,poz,val);
    aint[ind][nod] = max (aint[ind][nod<<1], aint[ind][nod<<1|1]);
    return;
}
int query (int nod, int st, int dr,int ind, int x, int y) {
    if (st > y || dr < x) {
        return 0;
    }
    if (st >= x && dr <= y) {
        return aint[ind][nod];
    }
    int mid = (st + dr) >> 1;
    int stanga = query (nod<<1,st,mid,ind,x,y);
    int dreapta = query (nod<<1|1,mid+1,dr,ind,x,y);
    return max (stanga, dreapta);
}

// main
int main (void) {
    in >> n >> q;
    for (int i = 1; i <= n; i ++) {
        in >> valoare[i];
    }
    for (int i = 1; i < n; i ++) {
        in >> a >> b;
        v[a].push_back (b);
        v[b].push_back (a);
    }
    dfs (1,1);
    // creeaza aint pentru fiecare lant
    for (int i = 1; i <= l; i ++) {
        sort (start[i].begin(), start[i].end(), cmp);
        for (int j = 0; j < start[i].size(); j ++) {
            poz[start[i][j]] = j + 1;
        }
        for (int j = 0; j <= start[i].size()*4; j++) {
            aint[i].push_back (0);
        }
        build (1,1,start[i].size(),i);
    }
    //operatii
    for (int i = 1; i <= q; i ++) {
        in >> t;
        if (t == 0) {
            in >> x >> y;
            update(1,1,start[lant[x]].size(),lant[x],poz[x],y);
        }
        if (t == 1) {
            in >> x >> y;
            int maxim = 0;
            while (lant[x] != lant[y]) {
                if (level[nod_tata[lant[x]]] > level[nod_tata[lant[y]]]) {
                    maxim = max (maxim, query (1,1,start[lant[x]].size(),lant[x],1,poz[x]) );
                    x = nod_tata[lant[x]];
                }
                else {
                    maxim = max (maxim, query (1,1,start[lant[y]].size(),lant[y],1,poz[y]) );
                    y = nod_tata[lant[y]];
                }
            }
            maxim = max (maxim,query(1,1,start[lant[y]].size(),lant[x],min(poz[x],poz[y]),max(poz[x],poz[y])));
            out << maxim <<"\n";
        }
    }
    return 0;
}