Cod sursa(job #2671125)

Utilizator PopescuAndreiAlexandruPopescu Andrei Alexandru PopescuAndreiAlexandru Data 11 noiembrie 2020 15:05:35
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.2 kb
#include <bits/stdc++.h>

using namespace std;

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

const int DIM = 100005;

int n,m,val[DIM],t,x,y,Cnt[DIM],nrChains=0,WhatChain[DIM],PosInChain[DIM];
int D[DIM],MaxSum[DIM],Best[DIM],Parent[DIM],Tree[DIM*4+5],Prev[DIM],ans;

bool seen[DIM];

vector <int> G[DIM],Chains[DIM];

void Read()
{
    fin>>n>>m;
    for(int i=1;i<=n;i++)
            fin>>val[i];
    for(int i=1;i<n;i++)
        {
            fin>>x>>y;
            G[x].push_back(y);
            G[y].push_back(x);
        }
}

void DFS(int node)
{
    Cnt[node]=1;
    vector <int> ::iterator it;
    for(it=G[node].begin();it!=G[node].end();it++)
        {
            if(!Cnt[*it])
                {
                    D[*it]=D[node]+1;
                    DFS(*it);
                    if(Cnt[*it]>MaxSum[node])
                        {
                            MaxSum[node]=Cnt[*it];
                            Best[node]=(*it);
                        }
                    Cnt[node]+=Cnt[*it];
                }
        }
}

void GetChains(int node)
{
    seen[node]=1;
    vector <int> ::iterator it;
    for(it=G[node].begin();it!=G[node].end();it++)
        {
            if(!seen[*it])
                    GetChains(*it);
        }
    if(Cnt[node]==1)
        {
            nrChains++;
            WhatChain[node]=nrChains;
            PosInChain[node]=1;
        }
    else
        {
            WhatChain[node]=WhatChain[Best[node]];
            PosInChain[node]=PosInChain[Best[node]]+1;
            for(it=G[node].begin();it!=G[node].end();it++)
                {
                    if((*it)!=Best[node])
                        Parent[WhatChain[*it]]=node;
                }
        }
    Chains[WhatChain[node]].push_back(node);
}

void UpdateTree(int nod, int st, int dr, int pos, int value)
{
    if(st==dr)
        {
            Tree[nod]=value;
            return;
        }
    int mij=(st+dr)>>1;
    if(pos<=mij)
        UpdateTree(2*nod,st,mij,pos,value);
    else
        UpdateTree(2*nod+1,mij+1,dr,pos,value);
    Tree[nod]=max(Tree[2*nod],Tree[2*nod+1]);
}

void QueryTree(int nod, int st, int dr, int a, int b)
{
    if(st>=a && dr<=b)
        {
            ans=max(ans,Tree[nod]);
            return;
        }
    int mij=(st+dr)>>1;
    if(a<=mij)
        QueryTree(2*nod,st,mij,a,b);
    if(b>mij)
        QueryTree(2*nod+1,mij+1,dr,a,b);
}

void Query()
{
    while(m--)
        {
            fin>>t>>x>>y;
            if(!t)
                UpdateTree(1,1,n,Prev[WhatChain[x]-1]+PosInChain[x],y);
            else
                {
                    ans=0;
                    while(WhatChain[x]!=WhatChain[y])
                        {
                            int p1=Chains[WhatChain[x]][Chains[WhatChain[x]].size()-1];
                            int p2=Chains[WhatChain[y]][Chains[WhatChain[y]].size()-1];
                            if(D[p1]>D[p2])
                                {
                                    QueryTree(1,1,n,Prev[WhatChain[x]-1]+PosInChain[x],Prev[WhatChain[x]]);
                                    x=Parent[WhatChain[x]];
                                }
                            else if(D[p1]<=D[p2])
                                {
                                    QueryTree(1,1,n,Prev[WhatChain[y]-1]+PosInChain[y],Prev[WhatChain[y]]);
                                    y=Parent[WhatChain[y]];
                                }
                        }
                    if(PosInChain[x]>PosInChain[y])
                        swap(x,y);
                    QueryTree(1,1,n,Prev[WhatChain[x]-1]+PosInChain[x],Prev[WhatChain[x]-1]+PosInChain[y]);
                    fout<<ans<<'\n';
                }
        }
}

void UpdateChains()
{
    int nr=0;
    for(int i=1;i<=nrChains;i++)
        {
            Prev[i]=Prev[i-1]+Chains[i].size();
            for(unsigned j=0;j<Chains[i].size();j++)
                {
                    nr++;
                    UpdateTree(1,1,n,nr,val[Chains[i][j]]);
                }
        }
}

int main()
{
    Read();
    DFS(1);
    GetChains(1);
    UpdateChains();
    Query();
}