Cod sursa(job #1430364)

Utilizator IonSebastianIon Sebastian IonSebastian Data 8 mai 2015 11:49:29
Problema Heavy Path Decomposition Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 7.59 kb
#include <cstdio>
#include <vector>
using namespace std;

class ArbIntNod {
public:
    int valoare;
    int st, dr;
    ArbIntNod *fs, *fd;

    ArbIntNod(int st, int dr)
    {
        this->valoare = 0;
        this->st = st;
        this->dr = dr;
        this->fs = NULL;
        this->fd = NULL;
    }
};

class ArbInt {
public:
    ArbIntNod* radacina;
    int dimensiune;

    //int *date;

    void makeArbInt(ArbIntNod* currNod)
    {
        if(currNod->st == currNod->dr)
            return;
        currNod->fs = new ArbIntNod(currNod->st,(currNod->st+currNod->dr)/2);
        makeArbInt(currNod->fs);
        currNod->fd = new ArbIntNod((currNod->st+currNod->dr)/2+1,currNod->dr);
        makeArbInt(currNod->fd);
    }

    ArbInt(int dimensiune) {
        this->radacina = new ArbIntNod(0,dimensiune-1);
        makeArbInt(radacina);
        /*this->dimensiune = dimensiune;
        this->date = new int[this->dimensiune];
        for(int i = 0; i < this->dimensiune; i++)
            this->date[i] = 0;*/
    }

    void update(int index, int valoare, ArbIntNod* currNod) {
        if(currNod->st == currNod->dr)
        {
            currNod->valoare = valoare;
            return;
        }
        if(index <= currNod->fs->dr) update(index, valoare, currNod->fs);
        else update(index, valoare, currNod->fd);
        currNod->valoare = max(currNod->fs->valoare, currNod->fd->valoare);
        //this->date[index] += valoare;
    }

    int queryMax(int inceput, int sfarsit, ArbIntNod *currNod) {
        if(currNod->st >= inceput && currNod->dr <= sfarsit) return currNod->valoare;
        int val1 = 0x80000000, val2 = 0x80000000;
        if(inceput <= currNod->fs->dr) val1 = queryMax(inceput, sfarsit, currNod->fs);
        if(currNod->fd->st <= sfarsit) val2 = queryMax(inceput, sfarsit, currNod->fd);
        return max(val1, val2);
        /*int answer = 0x80000000;
        for (int i = inceput; i <= sfarsit; ++i) {
            answer = max(answer, this->date[i]);
        }
        return answer;*/
    }

    void dump()
    {
        /*printf(" ( ");
        for(int i = 0; i < dimensiune; i++)
            printf("%3d ", date[i]);
        printf(")");*/
    }
};

class Nod;

class Lant {
public:
    Nod* primulNod;
    ArbInt* arbInt;
    int lungime; // ?

    Lant(Nod* primulNod)
    {
        this->primulNod = primulNod;
        this->lungime = 1;
    }

    void dump()
    {
        this->arbInt->dump();
    }

    void setArbInt() {
        this->arbInt = new ArbInt(this->lungime);
    }
};

class Nod {
public:
    //int index;
    int adancime;
    int greutate;
    Nod* tata;
    Nod* fiuGreu;
    vector<Nod*> vecini;
    Lant* lant;

    int valoare;

    Nod()
    {
        this->adancime = 0;
        this->greutate = 0;
        this->valoare = 0;
        this->fiuGreu = NULL;
    }

    void dump(bool cuLant = true, int offset = 0) {
        if (cuLant) {
            for (int i = 0; i < offset; ++i) {
                printf("             ");
                printf("             ");
            }
            Nod* nod = this;
            while (nod != NULL) {
                printf(" - %.8p (%.8p)", nod, nod->lant);
                fflush(stdout);
                nod = nod->fiuGreu;
            }
            this->lant->dump();
            printf("\n");
        }
        if(this->fiuGreu != NULL)
            this->fiuGreu->dump(false, offset + 1);
        for (int i = 0; i < (int)this->vecini.size(); ++i) {
            Nod* fiu = this->vecini[i];
            if (fiu != this->tata && fiu != this->fiuGreu) {
                fiu->dump(true, offset + 1);
            }
        }
    }

    void update(int valoare)
    {
        this->lant->arbInt->update(this->adancime-this->lant->primulNod->adancime, valoare, this->lant->arbInt->radacina);
    }
};

class Arbore {
    Nod* radacina;

    void dfs(Nod* nod)
    {
        nod->greutate = 1;
        for(int i = 0; i < (int)nod->vecini.size(); i++) {
            Nod* fiu = nod->vecini[i];
            if(fiu != nod->tata) {
                fiu->tata = nod;
                fiu->adancime = nod->adancime+1;
                dfs(fiu);
                nod->greutate += fiu->greutate;
                if(nod->fiuGreu == NULL || fiu->greutate > nod->fiuGreu->greutate)
                    nod->fiuGreu = fiu;
            }
        }
        if(nod->fiuGreu == NULL)
            nod->lant = new Lant(nod);
        else {
            nod->lant = nod->fiuGreu->lant;
            nod->lant->primulNod = nod;
            nod->lant->lungime++;
        }

        for(int i = 0; i < (int)nod->vecini.size(); i++) {
            Nod* fiu = nod->vecini[i];
            if(fiu != nod->tata && fiu != nod->fiuGreu)
                fiu->lant->setArbInt();
        }
    }
public:
    //Nod noduri[];
    Nod* noduri;

    Arbore(int N, int* muchii[2]) {
        this->noduri = new Nod[1 + N];
        this->radacina = &this->noduri[1];
        for(int i = 0; i < N-1; i++)
        {
            noduri[muchii[0][i]].vecini.push_back(&noduri[muchii[1][i]]);
            noduri[muchii[1][i]].vecini.push_back(&noduri[muchii[0][i]]);
        }
        this->radacina->adancime = 0;
        dfs(radacina);
        //for(;;);
        radacina->lant->setArbInt();
    }

    void dump() {
        this->radacina->dump();
        printf("\n");
    }

    int queryMax(int index1, int index2) {
        Nod* nod1 = &noduri[index1];
        Nod* nod2 = &noduri[index2];
        int maxim = 0;
        while(nod1->lant != nod2->lant) {

            if(nod1->lant->primulNod->adancime > nod2->lant->primulNod->adancime) {
                maxim = max(maxim, nod1->lant->arbInt->queryMax(0, nod1->adancime - nod1->lant->primulNod->adancime, nod1->lant->arbInt->radacina));
                nod1 = nod1->lant->primulNod->tata;
            } else {
                maxim = max(maxim, nod2->lant->arbInt->queryMax(0, nod2->adancime - nod2->lant->primulNod->adancime, nod2->lant->arbInt->radacina));
                nod2 = nod2->lant->primulNod->tata;
            }
        }
        int lung = nod1->lant->primulNod->adancime;
        if(nod1->adancime > nod2->adancime)
            maxim = max(maxim, nod1->lant->arbInt->queryMax(nod2->adancime-lung, nod1->adancime-lung, nod1->lant->arbInt->radacina));
        else
            maxim = max(maxim, nod1->lant->arbInt->queryMax(nod1->adancime-lung, nod2->adancime-lung, nod1->lant->arbInt->radacina));
        return maxim;
    }

    void update(int index, int valoare) {
        noduri[index].update(valoare);
    }
};

int main(void) {
    freopen("heavypath.in", "r", stdin);
    freopen("heavypath.out", "w", stdout);
    int n, m;
    int* muchii[2];
    scanf("%d%d", &n,&m);
    muchii[0] = new int[n-1];
    muchii[1] = new int[n-1];
    for(int i = 0; i < n; i++)
        scanf("%d%d", &muchii[0][i], &muchii[1][i]);

    Arbore* arbore = new Arbore(n, muchii);
    int type,x,y;
    for(int i = 0; i < m; i++)
    {
        scanf("%d%d%d", &type, &x, &y);
        if(type == 0)
            arbore->update(x,y);
        else
            printf("%d\n", arbore->queryMax(x,y));
    }
    /*int i;
    int arg1, arg2;
    int N, Q;
    int* muchii[2];
    char ch;

    scanf("%d", &N);
    muchii[0] = new int[N - 1];
    muchii[1] = new int[N - 1];
    for (i = 0; i < N - 1; ++i) {
        scanf("%d %d", &muchii[0][i], &muchii[1][i]);
    }
    Arbore* arbore = new Arbore(N, muchii);
    //arbore->dump();
    scanf("%d", &Q);
    for (int i = 0; i < Q; ++i) {
        scanf("\n%c %d %d", &ch, &arg1, &arg2);
        if (ch == 'I') {
            arbore->update(arg1, arg2);
        } else if (ch == 'G') {
            printf("%d\n", arbore->queryMax(arg1, arg2));
        }
      //  arbore->dump();
    }*/
    return 0;
}