Cod sursa(job #1140468)

Utilizator gabrielinelusGabriel-Robert Inelus gabrielinelus Data 12 martie 2014 00:17:19
Problema Heavy Path Decomposition Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 4.34 kb
#include <cstdio>
#include <vector>
#include <algorithm>
#include <vector>
#include <bitset>
#include <cmath>

#define Nmax 100005
#define INF 0x3f3f3f3f

using namespace std;
int N,Q,val[Nmax],weight[Nmax],height[Nmax],pozL[Nmax],care[Nmax];
int tata[Nmax],nrl = 1,pos,_newval,answer,A,B;
vector<int> G[Nmax];
bitset<Nmax> used,uzus;
vector<int> range[Nmax],lantz[Nmax];

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

void read()
{
    scanf("%d%d",&N,&Q);
    for(int i = 1; i <= N; ++i)
        scanf("%d",&val[i]);
    int a,b;
    for(int i = 1; i < N; ++i)
    {
        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])
        {
            height[*it] = height[k] + 1;
            DFS(*it);
        }
    weight[k] = 1;
    for(vector<int>::iterator it = G[k].begin(); it != G[k].end(); ++it)
        weight[k] += weight[*it];
}

void descompune(int k)
{
    used[k] = 1;
    care[k] = nrl;
    lantz[nrl].push_back(k);
    for(vector<int>::iterator it = G[k].begin(); it != G[k].end(); ++it)
        if(!used[*it])
        {
            if(!uzus[k])
            {
                uzus[k] = 1;
                descompune(*it);
            }
            else
            {
                tata[++nrl] = k;
                lantz[nrl].push_back(0);
                descompune(*it);
            }
        }
}

class SegmentTree{
public:
    void Build(int li,int lf,int pz,int linie)
    {
        if(li == lf)
        {
            range[linie][pz] = val[lantz[linie][li]];
            return;
        }
        int m = li + ((lf-li)>>1);
        Build(li,m,pz<<1,linie);
        Build(m+1,lf,(pz<<1)|1,linie);
        range[linie][pz] = max(range[linie][pz<<1],range[linie][(pz<<1)|1]);
    }
    void Update(int li,int lf,int pz,int linie)
    {
        if(li == lf)
        {
            range[linie][pz] = _newval;
            return;
        }
        int m = li + ((lf-li)>>1);
        if(pos <= m) Update(li,m,pz<<1,linie);
        else Update(m+1,lf,(pz<<1)|1,linie);
        range[linie][pz] = max(range[linie][pz<<1],range[linie][(pz<<1)|1]);
    }
    void Querry(int li,int lf,int pz,int line)
    {
        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,line);
        if(m < B) Querry(m+1,lf,(pz<<1)|1,line);
    }
}Aint;

void decompoz()
{
    height[1] = 1;
    DFS(1);
    used = 0;lantz[1].push_back(0);
    for(int i = 1; i <= N; ++i)
        sort(G[i].begin(),G[i].end(),cmp());
    descompune(1);
    for(int i = 1; i <= N; ++i)
    {
        for(int j = 1; j <= (1 << ((int)(log2(lantz[i].size()))+1) ) + 1; ++j )
            range[i].push_back(0);
    }
    for(int i = 1; i <= nrl; ++i)
        for(int j = 1; j < lantz[i].size(); ++j)
            pozL[lantz[i][j]] = j;
}

void make_tree()
{
    for(int i = 1; i <= nrl; ++i)
        Aint.Build(1,lantz[i].size()-1,1,i);

}

void solve()
{
    int tip,a,b,lan,tasu;
    for(int i = 1; i <= Q; ++i)
    {
        scanf("%d%d%d",&tip,&a,&b);
        if(tip == 0)
        {
            _newval = b;
            lan = care[a];
            pos = pozL[a];
            Aint.Update(1,lantz[lan].size()-1,1,lan);
        }
        else
        {
            if(height[a] < height[b])swap(a,b);
            answer = -INF;
            while(care[a] != care[b])
            {
                if(height[a] < height[b]) swap(a,b);
                if(care[a] == 1)swap(a,b);
                A = 1;
                B = pozL[a];
                Aint.Querry(1,lantz[care[a]].size()-1,1,care[a]);
                a = tata[care[a]];
            }
            A = pozL[a];
            B = pozL[b];
            if(A > B) swap(A,B);
            Aint.Querry(1,lantz[care[a]].size()-1,1,care[a]);
            printf("%d\n",answer);
        }
    }
}

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

    read();
    decompoz();
    make_tree();
    solve();
    return 0;
}