Cod sursa(job #2092486)

Utilizator Alex18maiAlex Enache Alex18mai Data 21 decembrie 2017 19:28:21
Problema Heavy Path Decomposition Scor 60
Compilator cpp Status done
Runda Arhiva educationala Marime 4.94 kb
#include <fstream>
#include <vector>

using namespace std;

//ifstream cin("heavypath.in");
ofstream cout("heavypath.out");

int val [100100];

vector < vector < int > > gr (100100);
vector < bool > used (100100);

vector < vector < int > > arb (100100);
vector < vector < int > > Arb (100100);
vector < int > tata_lant (100100);
vector < int > lant (100100);
vector < int > lv (100100);
vector < int > pos (100100);
int cont = 0;

class InParser {
private:
    FILE *fin;
    char *buff;
    int sp;

    char read_ch() {
        ++sp;
        if (sp == 4096) {
            sp = 0;
            fread(buff, 1, 4096, fin);
        }
        return buff[sp];
    }

public:
    InParser(const char* nume) {
        fin = fopen(nume, "r");
        buff = new char[4096]();
        sp = 4095;
    }

    InParser& operator >> (int &n) {
        char c;
        while (!isdigit(c = read_ch()) && c != '-');
        int sgn = 1;
        if (c == '-') {
            n = 0;
            sgn = -1;
        } else {
            n = c - '0';
        }
        while (isdigit(c = read_ch())) {
            n = 10 * n + c - '0';
        }
        n *= sgn;
        return *this;
    }

    InParser& operator >> (long long &n) {
        char c;
        n = 0;
        while (!isdigit(c = read_ch()) && c != '-');
        long long sgn = 1;
        if (c == '-') {
            n = 0;
            sgn = -1;
        } else {
            n = c - '0';
        }
        while (isdigit(c = read_ch())) {
            n = 10 * n + c - '0';
        }
        n *= sgn;
        return *this;
    }
};

int dfs(int root){

    used[root] = true;
    int MAX = 0;
    int go = 0;
    int last = 0;

    for (auto &x : gr[root]){
        if (used[x]){
            last = x;
            continue;
        }
        lv[x] = lv[root] + 1;
        int val = dfs(x);
        if (MAX < val){
            MAX = val;
            go = x;
        }
    }

    if (go == 0){
        cont++;
        arb[cont].push_back(root);
        lant[root] = cont;
        pos[root] = 1;
    }

    else{
        arb[lant[go]].push_back(root);
        lant[root] = lant[go];
        pos[root] = arb[lant[root]].size();
        for (auto &x : gr[root]){
            if (x == last || x == go){
                continue;
            }
            tata_lant [lant[x]] = root;
        }
    }

    return MAX + 1;

}

void Resize(){

    for (int i=1; i<=cont; i++){
        Arb[i].resize(arb[i].size() * 4);
    }

}

int st , dr , poz , value , ARB;

void Update (int nod){

    if (st == dr){
        Arb[ARB][nod] = value;
        return;
    }

    int mij = st + dr;
    mij /= 2;

    if (mij >= poz){
        dr = mij;
        Update(nod * 2);
    }
    else{
        st = mij + 1;
        Update(nod * 2 + 1);
    }

    Arb[ARB][nod] = max ( Arb[ARB][nod * 2] , Arb[ARB][nod * 2 + 1] );

}

int MIN , MAX;

void Querry (int NOD , int ST , int DR , int &maxx){

    if (MIN <= ST && MAX >= DR){
        maxx = max ( maxx , Arb[ARB][NOD] );
        return;
    }

    int mij = ST + DR;
    mij /= 2;

    if (mij >= MIN){
        Querry (NOD * 2 , ST , mij , maxx);
    }
    if (mij < MAX){
        Querry (NOD * 2  + 1, mij + 1 , DR , maxx);
    }

}

int main() {

    InParser fin("heavypath.in");

    ios::sync_with_stdio(false);
    cout.tie(NULL);

    int n , m;
    fin>>n>>m;

    for (int i=1; i<=n; i++){
        fin>>val[i];
    }

    for (int i=1; i<n; i++){
        int a , b;
        fin>>a>>b;
        gr[a].push_back(b);
        gr[b].push_back(a);
    }

    dfs(1);

    Resize();

    for (int i=1; i<=n; i++){
        st = 1;
        dr = arb[lant[i]].size();
        poz = pos[i];
        value = val[i];
        ARB = lant[i];
        Update (1);
    }

    for (int i=1; i<=m; i++){
        int test , x , y;
        fin>>test>>x>>y;

        if (test == 0){
            val[x] = y;
            st = 1;
            dr = arb[lant[x]].size();
            poz = pos[x];
            value = val[x];
            ARB = lant[x];
            Update (1);
        }

        else{
            int maxx = 0;
            while ( lant[x] != lant[y] ){

                int lv_x = lv [ arb [lant[x]] [arb [ lant[x] ].size() - 1 ]];
                int lv_y = lv [ arb [lant[y]] [arb [ lant[y] ].size() - 1 ]];

                if (lv_x > lv_y){
                    MIN = pos[x];
                    MAX = arb[lant[x]].size();
                    ARB = lant[x];
                    Querry(1, 1 , arb[lant[x]].size() , maxx);
                    x = tata_lant[lant[x]];
                }
                else{
                    MIN = pos[y];
                    MAX = arb[lant[y]].size();
                    ARB = lant[y];
                    Querry(1, 1 , arb[lant[y]].size() , maxx);
                    y = tata_lant[lant[y]];
                }

            }
            MIN = min(pos[x] , pos[y]);
            MAX = max(pos[x] , pos[y]);
            ARB = lant[x];
            Querry(1, 1 , arb[lant[x]].size() , maxx);

            cout<<maxx<<'\n';

        }

    }

    return 0;
}