Cod sursa(job #2277774)

Utilizator savulescustefanSavulescu Stefan savulescustefan Data 6 noiembrie 2018 20:28:34
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.5 kb
#include <cstdio>
#include <vector>
using namespace std;
vector <int> m2[100004],m3[100004],v[100004];
int n,m,i,j,x,y,c,z,q,w,nr,nr3,poz1,poz2,Max,k,aux,nr4,Min,t[100004],a[100004],r[200008],p[524292],s[100004],l[100004],poz[100004],le[100004],pr[100004];
bool ok;
void query (int st, int dr, int poz1, int poz2, int nod)
{
    if ((st>=poz1) && (dr<=poz2))
    {
        if (Max<m3[i][nod])
            Max=m3[i][nod];
        return;
    }
    if (((st+dr)/2)>=poz1)
        query(st,(st+dr)/2,poz1,poz2,nod*2);
    if ((((st+dr)/2)+1)<=poz2)
        query(((st+dr)/2)+1,dr,poz1,poz2,(nod*2)+1);
}
void up (int st, int dr, int nod)
{
    if (st==dr)
    {
        m3[i][nod]=x;
        return;
    }
    if (((st+dr)/2)>=poz1)
        up(st,(st+dr)/2,nod*2);
    else
        up(((st+dr)/2)+1,dr,nod*2+1);
    if (m3[i][nod*2]>m3[i][(nod*2)+1])
        m3[i][nod]=m3[i][nod*2];
    else
        m3[i][nod]=m3[i][(nod*2)+1];
    return;
}
void up2 (int st, int dr, int nod)
{
    if (st==dr)
    {
        p[nod]=x;
        return;
    }
    if (((st+dr)/2)>=i)
        up2(st,(st+dr)/2,nod*2);
    else
        up2(((st+dr)/2)+1,dr,nod*2+1);
    if (le[p[nod*2]]<le[p[(nod*2)+1]])
        p[nod]=p[nod*2];
    else
        p[nod]=p[(nod*2)+1];
    return;
}
void query2 (int st, int dr, int poz1, int poz2, int nod)
{
    if ((st>=poz1) && (dr<=poz2))
    {
        if (Min>le[p[nod]])
        {
            Min=le[p[nod]];
            w=p[nod];
        }
        return;
    }
    if (((st+dr)/2)>=poz1)
        query2(st,(st+dr)/2,poz1,poz2,nod*2);
    if ((((st+dr)/2)+1)<=poz2)
        query2(((st+dr)/2)+1,dr,poz1,poz2,nod*2);
    return;
}
void g (int x)
{
    int i,k;
    k=v[x].size();
    k--;
    for (i=0;i<=k;i++)
    {
        if (le[v[x][i]]==0)
        {
            le[v[x][i]]=le[x]+1;
            r[++nr3]=v[x][i];
            pr[v[x][i]]=nr3;
            nr4++;
            g(v[x][i]);
            r[++nr3]=x;
            if (s[v[x][i]]>Max)
            {
                Max=s[v[x][i]];
                poz1=v[x][i];
            }
        }
    }
    Max=-1;
    poz1=0;
    nr4=0;
    ok=true;
    for (i=0;i<=k;i++)
    {
        if (le[v[x][i]]>le[x])
        {
            if (s[v[x][i]]>Max)
            {
                Max=s[v[x][i]];
                poz1=v[x][i];
            }
            ok=false;
            nr4++;
        }
    }
    if (ok==true)
    {
        s[x]=1;
        nr++;
        l[x]=nr;
        poz[x]=1;
        m2[nr].push_back(x);
        return;
    }
    l[x]=l[poz1];
    poz[x]=poz[poz1]+1;
    m2[l[x]].push_back(x);
    s[x]=s[poz1]+nr4;
    for (i=0;i<=k;i++)
    {
        if ((v[x][i]!=poz1) && (le[x]<le[v[x][i]]))
            t[l[v[x][i]]]=x;
    }
    return;
}
void f (int x,int y)
{
    while (l[x]!=l[y])
    {
        z=l[y];
        i=z;
        poz1=poz[y]-1;
        k=m2[z].size();
        k--;
        query(0,k,poz1,k,1);
        y=t[l[y]];
    }
    z=l[x];
    i=z;
    poz1=poz[x]-1;
    poz2=poz[y]-1;
    k=m2[z].size();
    k--;
    query(0,k,poz2,poz1,1);
}
int main()
{
    freopen ("heavypath.in","r",stdin);
    freopen ("heavypath.out","w",stdout);
    scanf ("%d %d", &n, &m);
    for (i=1;i<=n;i++)
        scanf ("%d", &a[i]);
    for (i=1;i<=(n-1);i++)
    {
        scanf ("%d %d", &x, &y);
        v[x].push_back(y);
        v[y].push_back(x);
    }
    le[1]=1;
    r[1]=1;
    nr3=1;
    pr[1]=1;
    g(1);
    for (i=1;i<=nr3;i++)
    {
        x=r[i];
        up2(1,nr3,1);
    }
    for (i=1;i<=nr;i++)
    {
        k=m2[i].size();
        k*=3;
        for (j=1;j<=k;j++)
            m3[i].push_back(-1);
        k/=3;
        k--;
        for (j=0;j<=k;j++)
        {
            x=a[m2[i][j]];
            poz1=j;
            up(0,k,1);
        }
    }
    for (j=1;j<=m;j++)
    {
        scanf ("%d %d %d", &c, &x, &y);
        if (c==1)
        {
            z=pr[x];
            q=pr[y];
            if (z>q)
            {
                aux=z;
                z=q;
                q=aux;
            }
            Min=2000000000;
            query2(1,nr3,z,q,1);
            Max=-1;
            f(w,x);
            f(w,y);
            printf ("%d\n", Max);
        }
        else
        {
            z=l[x];
            poz1=poz[x]-1;
            i=z;
            x=y;
            k=m2[z].size();
            k--;
            up(0,k,poz1);
        }
    }
    return 0;
}