Cod sursa(job #2634510)

Utilizator StanCatalinStanCatalin StanCatalin Data 11 iulie 2020 11:54:51
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.99 kb
#include <iostream>
#include <vector>
#include <fstream>
#include <algorithm>

using namespace std;

ifstream in("heavypath.in");
ofstream out("heavypath.out");

const int dim = 1e5 + 5;

int n,m,v[dim];
vector <int> g[dim],lanturi[dim];
int lant[dim],weight[dim],height[dim],tata_lant[dim],pathgap[dim],cnt_lanturi;
int arb[4*dim],ans;

void DFS(int x,int parent)
{
    int ma = 0;
    height[x] = height[parent] + 1;
    weight[x] = 1;
    for (int i=0; i<g[x].size(); i++)
    {
        int y = g[x][i];
        if (y != parent)
        {
            DFS(y,x);
            weight[x] += weight[y];
            if (ma == 0 || weight[ma] < weight[y])
            {
                ma = y;
            }
        }
    }

    if (g[x].size() == 1 && x != 1)
    {
        cnt_lanturi++;
        lant[x] = cnt_lanturi;
        lanturi[cnt_lanturi].push_back(x);
        return ;
    }
    lant[x] = lant[ma];
    lanturi[lant[x]].push_back(x);
    for (int i=0; i<g[x].size(); i++)
    {
        int y = g[x][i];
        if (y != parent && y != ma)
        {
            tata_lant[lant[y]] = x;
        }
    }
}

void Build(int n,int st,int dr,int gap,int path)
{
    if (st == dr)
    {
        arb[n + gap] = v[lanturi[path][st-1]];
        return ;
    }
    int mid = (st+dr)/2;
    Build(2*n,st,mid,gap,path);
    Build(2*n+1,mid+1,dr,gap,path);
    arb[n+gap] = max(arb[2*n+gap],arb[2*n+1+gap]);
}

void Update(int n,int st,int dr,int pos,int val,int gap)
{
    if (st == dr)
    {
        arb[n + gap] = val;
        return ;
    }
    int mid = (st+dr)/2;
    if (pos <= mid)
    {
        Update(2*n,st,mid,pos,val,gap);
    }
    else
    {
        Update(2*n+1,mid+1,dr,pos,val,gap);
    }
    arb[n+gap] = max(arb[2*n+gap],arb[2*n+1+gap]);
}

void Query(int n,int st,int dr,int lq,int rq,int gap)
{
    //if (p == 1) cout << n << " " << st << " " << dr << " " << lq << " " << rq << " " << gap;
    if (lq <= st && dr <= rq)
    {
        ans = max(ans, arb[n+gap]);
        return ;
    }
    int mid = (st+dr)/2;
    if (lq <= mid)
    {
        Query(2*n,st,mid,lq,rq,gap);
    }
    if (rq >= mid+1)
    {
        Query(2*n+1,mid+1,dr,lq,rq,gap);
    }
}

void Heavypath()
{
    DFS(1,0);
    for (int i=1; i<=cnt_lanturi; i++)
    {
        reverse(lanturi[i].begin(), lanturi[i].end());
        if (i > 1)
        {
            pathgap[i] = pathgap[i-1] + 4*lanturi[i-1].size();
        }
        Build(1,1,lanturi[i].size(), pathgap[i], i);
    }
}

int main()
{
    in >> n >> m;
    for (int i=1; i<=n; i++)
    {
        in >> v[i];
    }
    for (int i=1; i<n; i++)
    {
        int x,y;
        in >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    Heavypath();
   /// cout << tata_lant[lant[6]];
   /// cout << lant[6];
    while (m--)
    {
        int x,y,t;
        in >> t >> x >> y;
       /// cout << x << " " << y << " " << lant[x] << " " << lant[y] << "\n";
        if (t == 0)
        {
            v[x] = y;
            Update(1,1,lanturi[lant[x]].size(), height[x] - height[tata_lant[lant[x]]], y, pathgap[lant[x]]);
        }
        else
        {
            ans = 0;
            while (1)
            {
                ///cout << x << " " << y << "\n";
                if (lant[x] == lant[y])
                {
                    if (height[x] > height[y]) swap(x,y);
                    ///cout << lanturi[ lant[x] ].size() << "\n";
                    Query(1,1,lanturi[ lant[x] ].size(),height[x] - height[tata_lant[lant[x]]],height[y] - height[tata_lant[lant[y]]], pathgap[lant[x]]);
                    break;
                }
                if (height[tata_lant[lant[x]]] < height[tata_lant[lant[y]]]) swap(x,y);
                Query(1,1,lanturi[ lant[x] ].size(),1,height[x] - height[tata_lant[lant[x]]], pathgap[lant[x]]);
                x = tata_lant[lant[x]];
            }
            out << ans << "\n";
        }
    }
    return 0;
}