Cod sursa(job #1225537)

Utilizator gabrielinelusGabriel-Robert Inelus gabrielinelus Data 2 septembrie 2014 19:28:59
Problema Heavy Path Decomposition Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 4.87 kb
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <bitset>
#include <cmath>

#define Nmax 100005
#define DIM 666013
#define next ((++pointer) == DIM) ? (fread(buffer,1,DIM,stdin),pointer = 0) : 0

char buffer[DIM];
int pointer = DIM - 1;

void scanf( int &A )
{
    A = 0;
    for(;'0' > buffer[pointer] || buffer[pointer] > '9';next);
    for(;'0' <= buffer[pointer] && buffer[pointer] <= '9'; next)
        A = A * 10 + buffer[pointer] - 48;
}


using namespace std;

int valori[Nmax];
int care_lantz[Nmax]; /// care_lantz[i] -> in ce lantz se afla i
int tata_lantz[Nmax]; /// tata_lantz[i] -> de ce nod se leaga lantul i
int greutate[Nmax]; /// greutate[i] -> greutatea nodului i
int poz_lantz[Nmax]; /// poz_lantz[i] -> pozitia in lantz a nodului i
int adancime[Nmax]; /// adancime[i] -> adancimea nodului i

int nrl = 1,N,M; /// nr lantzuri
int A,B,_newX,pos,answer,lc;

vector<int> G[Nmax];
vector<int> lantz[Nmax];
bitset<Nmax> used;


class cmp{
public:
    bool operator()(const int &x1,const int &x2) const{
        return greutate[x1] > greutate[x2];
    }
};

class SegmentTree{
private:
    vector<int> range;
public:
    void dimensiune(int k)
    {
        int x = 3*(k+1) ;
        range.resize( x );
    }
    void Build(int li,int lf,int pz)
    {
        if(li == lf)
        {
            range[pz] = valori[lantz[lc][li]];
            return;
        }
        int m = li + ((lf - li) >> 1);
        Build(li,m,pz<<1);
        Build(m+1,lf,(pz<<1)|1);
        range[pz] = max(range[pz<<1],range[(pz<<1)|1]);
    }
    void Update(int li,int lf,int pz)
    {
        if(li == lf)
        {
            range[pz] = _newX;
            return;
        }
        int m = li + ((lf - li) >> 1);
        if(pos <= m)Update(li,m,pz<<1);
        else Update(m+1,lf,(pz<<1)|1);
        range[pz] = max(range[pz<<1],range[(pz<<1)|1]);
    }
    void Querry(int li,int lf,int pz)
    {
        if(A <= li && lf <= B)
        {
            answer = max(answer,range[pz]);
            return;
        }
        int m = li +((lf - li) >> 1);
        if(A <= m) Querry(li,m,pz<<1);
        if(B > m) Querry(m+1,lf, (pz<<1)|1);
    }
}Aint[Nmax];

void read()
{
    scanf(N);
    scanf(M);
    for(int i = 1; i <= N; ++i)
        scanf(valori[i]);
}

void DFS_weight(int k)
{
    used[k] = 1;
    for(vector<int>::iterator it = G[k].begin(); it != G[k].end(); ++it)
        if(!used[*it])
        {
            adancime[*it] = adancime[k] + 1;
            DFS_weight(*it);
            greutate[k] += greutate[*it];
        }
    greutate[k] += 1; /// greutatea nodului curent
}

void build_tree()
{
    int a,b;
    for(int i = 1; i < N; ++i)
    {
        scanf(a),scanf(b);
        G[a].push_back(b);
        G[b].push_back(a);
    }
}

void decompose(int k)
{
    used[k] = 1;
    lantz[nrl].push_back(k);
    care_lantz[k] = nrl;
    poz_lantz[k] = lantz[nrl].size() - 1;
    for(vector<int>::iterator it = G[k].begin(); it != G[k].end(); ++it)
        if(!used[*it])
        {
            if(lantz[nrl].back() != k)
            {
                ++nrl;
                lantz[nrl].push_back(0);
                tata_lantz[nrl] = k;
            }
            decompose(*it);
        }
}

void path_decomposition()
{
    adancime[1] = 1;
    DFS_weight(1);
    used = 0;
    for(int i = 0; i <= N; ++i)
        sort(G[i].begin(),G[i].end(),cmp());
    lantz[nrl].push_back(0);
    decompose(1);
}

void raspunde(int nod1,int nod2)
{
    answer = -1;
    while(care_lantz[nod1] != care_lantz[nod2])
    {
        if(adancime[tata_lantz[care_lantz[nod1]]] < adancime[tata_lantz[care_lantz[nod2]]])
            swap(nod1,nod2);
        if(care_lantz[nod1] == 1)
            swap(nod1,nod2);
        lc = care_lantz[nod1];
        A = 1;
        B = poz_lantz[nod1];
        Aint[lc].Querry(1,lantz[lc].size()-1,1);
        nod1 = tata_lantz[lc];
    }
    lc = care_lantz[nod1];
    A = poz_lantz[nod1];
    B = poz_lantz[nod2];
    if(A > B) swap(A,B);
    Aint[lc].Querry(1,lantz[lc].size()-1,1);
    printf("%d\n",answer);
}

void querries()
{
    for(int i = 1; i <= nrl; ++i)
    {
        lc = i;/// lantul curent
        Aint[i].dimensiune(lantz[i].size());
        Aint[i].Build(1,lantz[i].size()-1,1);
    }
    int x,y,op;
    for(int i = 1; i <= M; ++i)
    {
        scanf(op);
        scanf(x),scanf(y);
        if(op == 0)
        {
            pos = poz_lantz[x];
            _newX = y;
            lc = care_lantz[x];
            Aint[lc].Update(1,lantz[lc].size()-1,1);
        }
        else
            raspunde(x,y);
    }
}

int main()
{
    freopen("heavypath.in","r",stdin);
    freopen("heavypath.out","w",stdout);

    read();
    build_tree();
    path_decomposition();
    querries();

    return 0;
}