Cod sursa(job #2739066)

Utilizator marinaoprOprea Marina marinaopr Data 6 aprilie 2021 19:18:42
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 5.03 kb
#include <stdio.h>
#include <vector>
#include <iostream>
#include <algorithm>

#define NMAX 100005

using namespace std;

FILE *fin = fopen("heavypath.in", "r");
FILE *fout = fopen("heavypath.out", "w");

vector <int> graf[NMAX];
vector <int> drum[NMAX];
vector <int> arbint[NMAX];

int n,m,t,x,y,a[NMAX],nrlant,lant[NMAX],tata[NMAX],nivel[NMAX],poz,ans,i,w[NMAX];
bool viz[NMAX];

void dfs(int nod, int niv)
{
    int maxim,imax,i,t,ultim;
//  fprintf(fout,"%d ",nod);
    viz[nod] = true;
    nivel[nod] = niv;

  /*  if(graf[nod].size() == 1)
    {
        nrlant++;
        lant[nod] = nrlant;
        drum[nrlant].push_back(nod);
        tata[nrlant] = graf[nod][0];
      //  return;
    }*/

    maxim = 0;
    int fii=0;
    w[nod]=1;
    for(i=0; i<=graf[nod].size()-1; ++i)
    {
        if(!viz[graf[nod][i]])
        {  fii++;

            dfs(graf[nod][i], niv+1);
             w[nod]+=w[graf[nod][i]];
            if(w[graf[nod][i]] > maxim)
            {
                maxim = w[graf[nod][i]];
                imax = lant[graf[nod][i]];
                ultim=graf[nod][i];
            }
        }
       // if(nivel[graf[nod][i]] < nivel[nod])
          //  t = graf[nod][i];
    }
    if(fii==0)
    {
        nrlant++;
        lant[nod] = nrlant;
        drum[nrlant].push_back(nod);
        w[nod]=1;
        return;
    }

    lant[nod] = imax;

    drum[imax].push_back(nod);
   // tata[imax] = t;
 //  fprintf(fout,"nodul %d se ataseaza nodului %d\n",nod,ultim);
     for(i=0; i<=graf[nod].size()-1; ++i)
     if( graf[nod][i]!=ultim and nivel[graf[nod][i]]>nivel[nod])
       {tata[lant[graf[nod][i]]]=nod;
     //  fprintf(fout,"%d este tatal lantului nodului %d cu numarul % d\n",nod, graf[nod][i], lant[graf[nod][i]]);
       }
}

void build(int index, int nod, int st, int dr)
{
    int mij;

    if(st == dr)
    {
        arbint[index][nod] = a[drum[index][st]];
        return;
    }

    mij = (st+dr) /2;
    build(index, 2*nod, st, mij);
    build(index, 2*nod+1, mij+1, dr);

    arbint[index][nod] = max(arbint[index][2*nod], arbint[index][2*nod+1]);
}

void update(int index, int nod, int st, int dr, int poz, int val)
{
    int mij;

    if(st == dr)
    {
        arbint[index][nod] = val;
        return;
    }

    mij = (st+dr) /2;
    if(poz <= mij)
        update(index, 2*nod, st, mij, poz, val);
    else
        update(index, 2*nod+1, mij+1, dr, poz, val);

    arbint[index][nod] = max(arbint[index][2*nod], arbint[index][2*nod+1]);
}

int query(int index, int nod, int st, int dr, int a, int b)
{
    int ans, mij;

    if(a<=st and dr<=b)
        return arbint[index][nod];

    ans = 0;
    mij = (st+dr) /2;
    if(a <= mij)
        ans = max(ans, query(index, 2*nod, st, mij, a, b));
    if(b > mij)
        ans = max(ans, query(index, 2*nod+1, mij+1, dr, a, b));
    return ans;
}

int main()
{
    fscanf(fin, "%d%d", &n,&m);
    for(i=1; i<=n; ++i)
        fscanf(fin, "%d", &a[i]);
    for(i=1; i<=n-1; ++i)
    {
        fscanf(fin, "%d%d", &x,&y);
        graf[x].push_back(y);
        graf[y].push_back(x);
    }

    dfs(1, 1);
//fprintf(fout,"\n");
    for(i=1; i<=nrlant; ++i)
    {
        reverse(drum[i].begin(), drum[i].end());
      // for(int k=0;k<drum[i].size();k++){
              //  int t=drum[i][k];
       // fprintf(fout,"%d ",t);}
          //  fprintf(fout,"tata %d si nivel tata %d  ",tata[i],nivel[tata[i]]);
      //  fprintf(fout,"\n");

        arbint[i].resize(4*drum[i].size());
    }

    for(i=1; i<=nrlant; ++i){
        build(i, 1, 0, drum[i].size()-1);
      //  for(int k=1;k<=12;k++)
          //  fprintf(fout,"%d  %d  ",k, arbint[i][k]);
     //   fprintf(fout,"\n");
    }


    while(m--)
    {
        fscanf(fin, "%d%d%d", &t,&x,&y);

        if(t == 0)
        {
            a[x] = y;
            poz = (-1)*(nivel[tata[lant[x]]] - nivel[x] + 1);
            update(lant[x], 1, 0, drum[lant[x]].size()-1, poz, y);
        }
        else
        {
            ans = 0;
            while(lant[x] != lant[y])
            {
                if(nivel[tata[lant[x]]] < nivel[tata[lant[y]]])
                    swap(x, y);
                int a=(-1)*( nivel[tata[lant[x]]] - nivel[x] + 1);
                int b=drum[lant[x]].size()-1;
                ans = max(ans, query(lant[x], 1, 0, drum[lant[x]].size()-1,0,(-1)*( nivel[tata[lant[x]]] - nivel[x] + 1)));
                x = tata[lant[x]];
            }

            if((nivel[tata[lant[x]]] - nivel[x] +1)*(-1) > (nivel[tata[lant[y]]]- nivel[y]+1)*(-1))
                swap(x,y);
              //  fprintf(fout,"%d %d %d  ", drum[lant[x]].size()-1, (-1)*(nivel[tata[lant[x]]] - nivel[x] + 1), (-1)*(nivel[tata[lant[y]]] - nivel[y] + 1));
            ans = max(ans, query(lant[x], 1, 0, drum[lant[x]].size()-1,(-1)*( nivel[tata[lant[x]]] - nivel[x] + 1), (-1)*(nivel[tata[lant[y]]] - nivel[y] + 1)));
            fprintf(fout, "%d\n", ans);
        }
    }

    fclose(fin);
    fclose(fout);
    return 0;
}