Cod sursa(job #1971179)

Utilizator radu.leonardoThe Doctor radu.leonardo Data 19 aprilie 2017 22:19:26
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.39 kb
#include <bits/stdc++.h>
#define MaxN 100001
using namespace std;
ifstream f("heavypath.in");
ofstream g("heavypath.out");
/* ==================== */
int N,T;
int Val[MaxN];
vector<int> G[MaxN];
/* ==================== */
vector<int> Path[MaxN];
int Parent[MaxN];
int whatPath[MaxN],patchN=0;
int PathDim[MaxN];
int PathPosition[MaxN];
int PathDepth[MaxN];
int whatPos[MaxN];
int subtreeNodes[MaxN];
int Depth[MaxN];
bitset<MaxN> Visited;
/* ==================== */
int Arbint[4*MaxN];
/* ==================== */

void read_data()
{
    f>>N>>T;
    for(int i=1;i<=N;i++) f>>Val[i];
    for(int i=1;i<N;i++)
    {
        int x,y;
        f>>x>>y;
        G[x].emplace_back(y);
        G[y].emplace_back(x);
    }
}

void DFS(int node)
{
    Visited[node]=1;
    subtreeNodes[node]=1;
    int isLeaf=1,heavyNode=-1;

    for(auto it:G[node])
        if(Visited[it]==0)
        {
            isLeaf=false;
            Depth[it] = Depth[node] + 1;
            DFS(it);
            subtreeNodes[node]+=subtreeNodes[it];

            if(heavyNode == -1) heavyNode = it;
            else if(subtreeNodes[heavyNode] < subtreeNodes[it])  heavyNode=it;
        }

    if(isLeaf)
    {
        whatPath[node] = ++patchN;
        PathDim[patchN]=1;
        Path[patchN].push_back(node);
        return;
    }

    whatPath[node] =whatPath[heavyNode];
    PathDim[whatPath[node]]++;
    Path[whatPath[node]].push_back(node);

    for(auto it:G[node])
    {
        if(it==heavyNode || Depth[it]<Depth[node])  continue;

        Parent[whatPath[it]]=node;
        PathDepth[whatPath[it]]=Depth[node];
    }
}

void Build(int node, int left, int right, int lastUsedPosition, int patchIndex)
{
    if(left == right)
    {
        Arbint[node + lastUsedPosition] =Val[ Path[patchIndex][left - 1] ];
        return;
    }

    int mid = (left + right) / 2;

    Build(node * 2    , left , mid  , lastUsedPosition, patchIndex);
    Build(node * 2 + 1, mid+1, right, lastUsedPosition, patchIndex);

    Arbint[node + lastUsedPosition] = max(Arbint[node * 2 + lastUsedPosition], Arbint[node * 2 + 1 + lastUsedPosition]);
}

void Update(int node, int left, int right, int poz, int val, int lastUsedPosition)
{
    if(left == right)
    {
        Arbint[node + lastUsedPosition] = val;
        return;
    }
    int mid = (left + right) / 2;
    if(poz<=mid)  Update(node * 2    , left , mid  , poz, val, lastUsedPosition);
    else          Update(node * 2 + 1, mid+1, right, poz, val, lastUsedPosition);

    Arbint[node + lastUsedPosition] = max(Arbint[node * 2 + lastUsedPosition], Arbint[node * 2 + 1 + lastUsedPosition]);
}

int Query(int node, int left, int right, int qleft, int qright, int lastUsedPosition)
{
    if(qleft <= left && right <= qright)
        return Arbint[node + lastUsedPosition];

    int mid=(left + right)/2, rez = 0;

    if(qleft <= mid)   rez = max(rez, Query(node * 2    , left   , mid  , qleft, qright, lastUsedPosition) );
    if(mid < qright)   rez = max(rez, Query(node * 2 + 1, mid + 1, right, qleft, qright, lastUsedPosition) );

    return rez;
}

void computePaths()
{
    Depth[1] = 1;
    DFS(1);

    for(int i = 1; i <= patchN; ++i)
    {
        reverse(Path[i].begin(), Path[i].end());
        if(i>1) PathPosition[i] = PathPosition[i-1] + PathDim[i-1] * 4;
        Build(1, 1,PathDim[i],PathPosition[i],i);
    }
}

int hQuery(int x,int y)
{
        int Answer = 0;
        while(1)
        {
            if(whatPath[x] == whatPath[y])
            {
                if(Depth[x] > Depth[y])  swap(x, y);
                Answer= max(Answer, Query(1, 1,PathDim[whatPath[x]],Depth[x] - PathDepth[whatPath[x]],Depth[y] - PathDepth[whatPath[y]], PathPosition[whatPath[x]] ));
                break;
            }

            if(PathDepth[whatPath[x]] < PathDepth[whatPath[y]]) swap(x, y);

            Answer=max(Answer, Query(1, 1,PathDim[whatPath[x]], 1,Depth[x] - PathDepth[whatPath[x]], PathPosition[whatPath[x]]) );

            x = Parent[whatPath[x]];
        }
        g<<Answer<<'\n';

}

void solve()
{
    while(T--)
    {
        int type,x,y;
        f>>type>>x>>y;
        if(type==0) Update(1, 1, PathDim[whatPath[x]], Depth[x] - PathDepth[whatPath[x]], y, PathPosition[whatPath[x]]);
        else hQuery(x,y);
    }
}

int main()
{
    read_data();
    computePaths();
    solve();

}