Cod sursa(job #2430879)

Utilizator NicolaalexandraNicola Alexandra Mihaela Nicolaalexandra Data 17 iunie 2019 01:47:20
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.84 kb
#include <fstream>
#include <iostream>
#include <vector>
#define DIM 300010
using namespace std;

ifstream fin ("heavypath.in");
ofstream fout ("heavypath.out");
int Size[DIM],whatChain[DIM],positionInChain[DIM],chainFatherNode[DIM],level[DIM];
int a[50][2*DIM],val[DIM],viz[DIM];
vector <int> chains[DIM],L[DIM];
int n,m,i,x,y,op,nr_chains,sol;
void dfs (int nod, int tata){
    viz[nod] = Size[nod] = 1;
    level[nod] = 1+level[tata];
    for (int i=0;i<L[nod].size();i++){
        int vecin = L[nod][i];
        if (!viz[vecin]){
            dfs (vecin,nod);
            Size[nod] += Size[vecin]; /// cate noduri am in subarbore
        }}
    if (L[nod].size() == 1 && nod != 1){ /// inseamna ca e frunza deci incep un nou lant
        nr_chains++;
        chains[nr_chains].push_back(0); /// le vreau indexate de la 1
        chains[nr_chains].push_back(nod);
        whatChain[nod] = nr_chains; /// pe ce lant se afla x
        positionInChain[nod] = 1; /// pozitia in lant
    } else {
        /// pun nodul curent la capatul lantului fiului cel mai "greu", adica cel care Size ul maxim
        int maxim = 0, poz = 0;
        for (int i=0;i<L[nod].size();i++){
            int fiu = L[nod][i];
            if (fiu == tata)
                continue;
            if (Size[fiu] > maxim){
                maxim = Size[fiu];
                poz = fiu;
            }}
        /// acum il atasez la fiu
        chains[whatChain[poz]].push_back(nod);
        whatChain[nod] = whatChain[poz];
        positionInChain[nod] = chains[whatChain[poz]].size()-1;
        /// acum calculez chain father node
        for (int i=0;i<L[nod].size();i++){
            int fiu = L[nod][i];
            if (fiu == tata)
                continue;
            if (fiu != poz)
                chainFatherNode[whatChain[fiu]] = nod;
        }}}
inline void build (int chain, int nod, int st, int dr){
    if (st == dr){
        a[chain][nod] = val[chains[chain][st]];
        return;
    }
    int mid = (st+dr)/2;
    build (chain,2*nod,st,mid);
    build (chain,2*nod+1,mid+1,dr);
    a[chain][nod] = max (a[chain][2*nod],a[chain][2*nod+1]);
}

inline void update (int chain, int nod, int st, int dr, int poz, int val){
    if (st == dr){
        a[chain][nod] = val;
        return;
    }
    int mid = (st+dr)/2;
    if (poz <= mid)
        update (chain,2*nod,st,mid,poz,val);
    else update (chain,2*nod+1,mid+1,dr,poz,val);
    a[chain][nod] = max (a[chain][2*nod],a[chain][2*nod+1]);
}
inline void query_aint (int chain, int nod, int st, int dr, int x, int y, int &maxi){
    if (x <= st && dr <= y){
        maxi = max (maxi,a[chain][nod]);
        return;
    }
    int mid = (st+dr)/2;
    if (x <= mid)
        query_aint (chain,2*nod,st,mid,x,y,maxi);
    if (y > mid)
        query_aint (chain,2*nod+1,mid+1,dr,x,y,maxi);
}
inline void query (int x, int y){
    if (x == y)
        return;
    if (whatChain[x] == whatChain[y]){ /// aici e simplu
        int maxi = 0;
        int posx = positionInChain[x];
        int posy = positionInChain[y];
        if (posx > posy)
            swap (posx,posy);
        query_aint (whatChain[x],1,1,chains[whatChain[x]].size()-1,posx,posy,maxi);
        sol = max (sol,maxi);
        return;
    }
    /// acum trebuie sa vad pe care il urc
    if (level[chainFatherNode[whatChain[x]]] > level[chainFatherNode[whatChain[y]]]){
        /// il urc pe x
        int maxi = 0;
        query_aint (whatChain[x],1,1,chains[whatChain[x]].size()-1,positionInChain[x],chains[whatChain[x]].size()-1,maxi);
        sol = max (sol,maxi);
        int nr = chainFatherNode[whatChain[x]]; /// nodul fix deasupra lantului lui x
        query (nr,y);
    } else {
        int maxi = 0;
        query_aint (whatChain[y],1,1,chains[whatChain[y]].size()-1,positionInChain[y],chains[whatChain[y]].size()-1,maxi);
        sol = max (sol,maxi);
        int nr = chainFatherNode[whatChain[y]];
        query (x,nr);
    }}
int main (){

    fin>>n>>m;
    for (i=1;i<=n;i++)
        fin>>val[i];
    for (i=1;i<n;i++){
        fin>>x>>y;
        L[x].push_back(y);
        L[y].push_back(x);
    }
    dfs (1,0);
    //for (i=1;i<=n;i++)
      //  cout<<whatChain[i]<<" "<<positionInChain[i]<<"\n";
   // for (i=1;i<=nr_chains;i++){
        //cout<<chainFatherNode[i]<<"\n";
     //   for (int j=1;j<chains[i].size();j++)
       //     cout<<chains[i][j]<<" ";
       // cout<<"\n";
    //}
    /// acum trebuie sa fac build ul la aint
    for (i=1;i<=nr_chains;i++)
        build (i,1,1,chains[i].size()-1);

    for (i=1;i<=m;i++){
        fin>>op>>x>>y;
        if (op == 0) /// update
            update (whatChain[x],1,1,chains[whatChain[x]].size()-1,positionInChain[x],y);
        else {
            sol = 0;
            query (x,y);
            fout<<sol<<"\n";
        }}


    return 0;
}