Cod sursa(job #1141068)

Utilizator gabrielinelusGabriel-Robert Inelus gabrielinelus Data 12 martie 2014 16:14:08
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 5.14 kb
#include <cstdio>
#include <vector>
#include <bitset>
#include <algorithm>
#include <cmath>

#define Nmax 100005
#define INF 0x3f3f3f3f

using namespace std;
int N,Q,valori[Nmax],nrl = 1;
bitset<Nmax> used;
vector<int> G[Nmax];
vector<int> lantz[Nmax]; /// lantz[i] -> lantzul cu nr de ordine i
vector<int> range[Nmax];

int greutate[Nmax]; /// greutate[i] -> numarul de descendenti ai lui i
int adancime[Nmax]; /// adancime[i] -> adancimea nodului i plecand din 1
int care[Nmax]; /// care[i] -> in care lantz se afla nodul i
int tata_lantz[Nmax]; /// tata_lantz[i] -> de ce nod se leaga lantzul din care face parte i
int pozitie_nod[Nmax]; /// pozitie_nod[i] -> locul in care se afla nodul in latzul din care face parte


#define DIM 500000
char buff[DIM];
int poZ=DIM-1;

void citeste(int &numar)
{
     numar = 0;
     while (buff[poZ] < '0' || buff[poZ] > '9')
          if (++poZ == DIM)
               fread(buff,1,DIM,stdin),poZ=0;
     while ('0'<=buff[poZ] && buff[poZ]<='9')
     {
          numar = numar*10 + buff[poZ] - '0';
          if (++poZ == DIM)
               fread(buff,1,DIM,stdin),poZ=0;
     }
}



class cmp{
public:
    bool operator()(const int x,const int y)const
    {
        return greutate[x] > greutate[y];
    }
};

void read()
{
    citeste(N),citeste(Q);///scanf("%d%d",&N,&Q);
    int a,b;
    for(int i = 1; i <= N; ++i) citeste(valori[i]);///scanf("%d",valori+i);
    for(int i = 1; i < N; ++i){
        citeste(a),citeste(b);///scanf("%d%d",&a,&b);
        G[a].push_back(b);
        G[b].push_back(a);
    }
}

void DFS(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(*it);
            }
    for(vector<int>::iterator it = G[k].begin(); it != G[k].end(); ++it)
        greutate[k] += greutate[*it];
    ++greutate[k];
}

void descomp(int k)
{
    care[k] = nrl;
    lantz[nrl].push_back(k); /// incepem descompunerea
    pozitie_nod[k] = lantz[nrl].size()-1;
    used[k] = 1;
    for(vector<int>::iterator it = G[k].begin(); it != G[k].end(); ++it)
        if(!used[*it])
        {
            if(lantz[nrl].size() == 1)
                tata_lantz[nrl] = k;
            descomp(*it);
        }
    if(G[k].size() == 1 && k != 1){
        ++ nrl; /// sunt intr-o frunzulitzaa
        lantz[nrl].push_back(0); /// jmenarim indexarea
    }
}

void decomposition()
{
    DFS(1);
    for(int i = 1; i <= N; ++i)
        sort(G[i].begin(),G[i].end(),cmp());
    adancime[1] = 1;
    used = 0; lantz[1].push_back(0);
    descomp(1); -- nrl;
    for(int i = 1; i <= nrl; ++i)
        for(int j = 0; j <= (1<<((int)log2(lantz[i].size())+ 1)) + 1 ; ++j)
            range[i].push_back(0);

}
int line,A,B,pos,_newX,answer;

class SegmentTree{
public:
    void Build(int li,int lf,int pz)
    {
        if(li == lf)
        {
            range[line][pz] = valori[lantz[line][li]];
            return;
        }
        int m = li + ((lf-li)>>1);
        Build(li,m,pz<<1);
        Build(m+1,lf,(pz<<1)|1);
        range[line][pz] = max(range[line][pz<<1],range[line][(pz<<1)|1]);
    }
    void Update(int li,int lf,int pz)
    {
        if(li == lf)
        {
            range[line][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[line][pz] = max(range[line][pz<<1],range[line][(pz<<1)|1]);
    }
    void Querry(int li,int lf,int pz)
    {
        if(A <= li && lf <= B)
        {
            answer = max(answer,range[line][pz]);
            return;
        }
        int m = li+((lf-li)>>1);
        if(A <= m) Querry(li,m,pz<<1);
        if(m < B) Querry(m+1,lf,(pz<<1)|1);
    }
    void Make()
    {
        for(int i = 1; i <= nrl; ++i)
        {
            line = i;
            Build(1,lantz[i].size()-1,1);
        }
    }

}Aint;

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

    read();
    decomposition();
    Aint.Make();
    int typ,x,y;
    for(int i = 1; i <= Q; ++i)
    {
        citeste(typ),citeste(x),citeste(y);
        ///scanf("%d%d%d",&typ,&x,&y);
        if(typ == 0)
        {
            _newX = y;
            pos = pozitie_nod[x];
            line = care[x];
            Aint.Update(1,lantz[line].size()-1,1);
        }
        else
        {
            answer = -INF;
            while(care[x] != care[y])
            {
                if(adancime[tata_lantz[care[x]]] < adancime[tata_lantz[care[y]]]) swap(x,y);
                line = care[x];
                A = 1;
                B = pozitie_nod[x];
                Aint.Querry(1,lantz[line].size()-1,1);
                x = tata_lantz[care[x]];
            }
            A = pozitie_nod[x];
            B = pozitie_nod[y];
            line = care[x];
            if(A > B) swap(A,B);
            Aint.Querry(1,lantz[line].size()-1,1);
            printf("%d\n",answer);
        }

    }

    return 0;
}