Cod sursa(job #3220655)

Utilizator solicasolica solica solica Data 4 aprilie 2024 16:05:36
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.66 kb
#include <fstream>
#include <vector>
#include <algorithm>

using namespace std;

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

#define NMAX 100008


int n,pn,q,i,j;

vector<int>muchii[NMAX],path[NMAX];

int a[NMAX],poz[NMAX],p[NMAX],lin[NMAX],depth[NMAX],nrp[NMAX];

int viz[NMAX];

struct segment_tree
{
    int tree[NMAX*4];
    void build (int node, int st, int dr)
    {
        if (st==dr)
        {
            tree[node]=a[lin[st]];
        }
        else
        {
            int mij=(st+dr)/2;
            build (node*2,st,mij);
            build (node*2+1,mij+1,dr);
            tree[node]=max(tree[node*2],tree[node*2+1]);
        }
    }
    void update (int node, int st, int dr, int poz, int val)
    {
        if (st==dr)
        {
            tree[node]=val;
        }
        else
        {
            int mij=(st+dr)/2;
            if (poz<=mij)
            {
                update(node*2,st,mij,poz,val);
            }
            else
            {
                update(node*2+1,mij+1,dr,poz,val);
            }
            tree[node]=max(tree[node*2],tree[node*2+1]);
        }
    }
    int query(int node, int st, int dr, int l, int r)
    {
        if (l<=st && dr<=r)
        {
            return tree[node];
        }
        else
        {
            int mij=(st+dr)/2;
            if (r<=mij)
            {
                return query(node*2,st,mij,l,r);
            }
            if (l>mij)
            {
                return query(node*2+1,mij+1,dr,l,r);
            }
            return max(query(node*2,st,mij,l,r),query(node*2+1,mij+1,dr,l,r));
        }
    }
}aint;

void dfs (int node, int ad);

void hld ();

void update_hld (int node, int val);

int query_hld (int a, int b);

int main()
{
    fin>>n>>q;
    for (i=1; i<=n; i++)
    {
        fin>>a[i];
    }
    for (i=1; i<n; i++)
    {
        int x,y;
        fin>>x>>y;
        muchii[x].push_back(y),muchii[y].push_back(x);
    }
    hld();
    for (i=1; i<=q; i++)
    {
        int type,x,y;
        fin>>type>>x>>y;
        if (type==0)
        {
            update_hld(x,y);
        }
        else
        {
            fout<<query_hld(x,y)<<'\n';
        }
    }
    return 0;
}

int query_hld (int a, int b)
{
    int answer=0;
    while (1)
    {
        if (depth[a]>depth[b])
        {
            swap(a,b);
        }
        if (nrp[a]==nrp[b])
        {
            answer=max(answer,aint.query(1,1,n,poz[a],poz[b]));
            return answer;
        }
        if (depth[path[nrp[a]][0]]>depth[path[nrp[b]][0]])
        {
            swap(a,b);
        }
        answer=max(answer,aint.query(1,1,n,poz[path[nrp[b]][0]],poz[b]));
        b=p[path[nrp[b]][0]];
    }
    return answer;
}

void update_hld (int node, int val)
{
    aint.update(1,1,n,poz[node],val);
}

void hld ()
{
    int i,ind=0;
    dfs(1,1);
    for (i=1; i<=pn; i++)
    {
        reverse(path[i].begin(),path[i].end());
        for (auto node : path[i])
        {
            lin[++ind]=node;
            poz[node]=ind;
        }
    }
    aint.build (1,1,n);
}

void dfs (int node, int ad)
{
    int maxi=0;
    viz[node]=1;
    depth[node]=ad;
    for (auto vec : muchii[node])
    {
        if (!viz[vec])
        {
            p[vec]=node;
            dfs(vec,ad+1);
            if (viz[vec]>maxi)
            {
                maxi=viz[vec];
                nrp[node]=nrp[vec];
            }
            viz[node]+=viz[vec];
        }
    }
    if (!nrp[node])
    {
        ++pn;
        nrp[node]=pn;
    }
    path[nrp[node]].push_back(node);
}