Cod sursa(job #2387256)

Utilizator CodrinsahCotarlan Codrin Codrinsah Data 24 martie 2019 14:27:14
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.09 kb
#include <fstream>
#include <vector>
#include <algorithm>
#define INF 100001
using namespace std;
ifstream fi ("heavypath.in");
ofstream fo ("heavypath.out");
vector<int> v[100005],vaux;
vector<vector<int>> lant,aib;
int nivel[100005],eul[200005],aiblca[8000005],firstpoz[100005],val[100005],reprez[100005],tata[100005],pozinlant[100005];
int nrnod,nrq,lgeul,nrlant;
bool comp(int a,int b)
{
    return nivel[a]<nivel[b];
}
int dfslant(int nod,int lvl,int prev)
{
    nivel[nod]=lvl;
    if (v[nod].size()==1 and prev!=0)
    {
        nrlant++;
        reprez[nod]=nrlant-1;
        lant.push_back(vaux);
        lant[nrlant-1].push_back(nod);
        return 1;
    }
    int stot=0,smax=0;
    for (int i=0;i<v[nod].size();i++)
    {
        int nextnod=v[nod][i];
        if (nextnod==prev) continue;
        int sum=dfslant(nextnod,lvl+1,nod);
        stot+=sum;
        if (sum>smax)
        {
            smax=sum;
            reprez[nod]=reprez[nextnod];
        }
    }
    lant[reprez[nod]].push_back(nod);
    for (int i=0;i<v[nod].size();i++)
    {
        int nextnod=v[nod][i];
        if (reprez[nod]!=reprez[nextnod]) tata[reprez[nextnod]]=nod;
    }
    return stot+1;
}
int genaib(int idx,int nod,int st,int dr)
{
    if (st==dr) return aib[idx][nod]=lant[idx][st];
    int mij=(st+dr)/2;
    int nod1=genaib(idx,nod*2,st,mij);
    int nod2=genaib(idx,nod*2+1,mij+1,dr);
    if (val[nod1]>val[nod2]) return aib[idx][nod]=nod1;
    else return aib[idx][nod]=nod2;
}
int update(int idx,int nod,int st,int dr,int nr,int valoare)
{
    int poz=pozinlant[nr];
    if (st==dr)
    {
        val[nr]=valoare;
        return nr;
    }
    int nod1=0,nod2=0;
    int mij=(st+dr)/2;
    if (poz<=mij)
    {
        nod1=update(idx,nod*2,st,mij,nr,valoare);
        nod2=aib[idx][nod*2+1];
    }
    else
    {
        nod1=aib[idx][nod*2];
        nod2=update(idx,nod*2+1,mij+1,dr,nr,valoare);
    }
    if (val[nod1]>=val[nod2]) return aib[idx][nod]=nod1;
    else aib[idx][nod]=nod2;
}
int qaib(int idx,int nod,int st,int dr,int start,int stop)
{
    if (start>stop) swap(start,stop);
    if (dr<start or st>stop) return 0;
    if (st>=start and dr<=stop) return aib[idx][nod];
    int mij=(st+dr)/2;
    int nod1=qaib(idx,nod*2,st,mij,start,stop);
    int nod2=qaib(idx,nod*2+1,mij+1,dr,start,stop);
    if (val[nod1]>val[nod2]) return nod1;
    else return nod2;
}
int querry(int nod1,int nod2)
{
    int idx1=reprez[nod1];
    int idx2=reprez[nod2];
    int nodcur=0;
    int nodaux=0;
    while (idx1!=idx2)
    {
        int tata1=tata[idx1];
        int tata2=tata[idx2];
        if (nivel[tata1]<nivel[tata2])
        {
            swap (tata1,tata2);
            swap(idx1,idx2);
            swap(nod1,nod2);
        }
        nodaux=qaib(idx1,1,0,lant[idx1].size()-1,0,pozinlant[nod1]);
        if (val[nodaux]>val[nodcur]) nodcur=nodaux;
        nod1=tata[idx1];
        idx1=reprez[nod1];
        idx2=reprez[nod2];
    }
//    nodaux=qaib(idx1,1,0,lant[idx1].size()-1,pozinlant[nod1],pozinlant[nod2]);
    if (nodcur==0) return val[nodaux];
    if (val[nodcur]>val[nodaux]) return val[nodcur];
    return val[nodaux];
}
int main()
{
    fi>>nrnod>>nrq;
    for (int i=1;i<=nrnod;i++) fi>>val[i];
    for (int i=1;i<nrnod;i++)
    {
        int x,y;
        fi>>x>>y;
        v[x].push_back(y);
        v[y].push_back(x);
    }
    nivel[INF]=INF;
    int aux=dfslant(1,0,0);
    for (int i=0;i<nrlant;i++) sort(lant[i].begin(),lant[i].end(),comp);
    for (int i=0;i<nrlant;i++)
        for (int j=0;j<lant[i].size();j++)
            pozinlant[lant[i][j]]=j;
    for (int i=0;i<nrlant;i++)
    {
        aib.push_back(vaux);
        for (int j=0;j<=lant[i].size()*4;j++) aib[i].push_back(-1);
        aux=genaib(i,1,0,lant[i].size()-1);
    }
    for (int i=1;i<=nrq;i++)
    {
        int p,x,y;
        fi>>p>>x>>y;
        if (p==0) aux=update(reprez[x],1,0,lant[reprez[x]].size()-1,x,y);
        if (p==1) fo<<querry(x,y)<<'\n';
    }
//    for (int i=1;i<aib[0].size();i++) fo<<aib[0][i]<<' ';
    return 0;
}