Cod sursa(job #2990490)

Utilizator TghicaGhica Tudor Tghica Data 7 martie 2023 22:39:28
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.82 kb
#include <fstream>
#include <algorithm>
#include <vector>

#define NMAX 100000

using namespace std;

ifstream cin("heavypath.in");
ofstream cout("heavypath.out");

struct nodeType{
  vector<int>edge;
  int grupa, ordNumber, depth;
}arb[NMAX + 1];

int pLight[NMAX + 1];

int aintGlobal[NMAX * 4], sizeOfGrupa[NMAX + 1], pozStartCur;
int* pozStartAint[NMAX + 1];
int v[NMAX + 1];

int dfs(int node, int p) {
  if(p != 0 && arb[node].edge.size() == 1) {
    arb[node].grupa = node;
    arb[node].ordNumber = 1;
    sizeOfGrupa[node] = 1;
    return 1;
  }
  int mxCopii = 0, vecinHeavy, vecin, nrCopii, totalCopii = 0;
  for(int i = 0; i < arb[node].edge.size(); i++) {
    vecin = arb[node].edge[i];
    if(vecin == p) {
      continue;
    }
    arb[vecin].depth = arb[node].depth + 1;
    nrCopii = dfs(vecin, node);
    totalCopii += nrCopii;
    if(nrCopii > mxCopii) {
      mxCopii = nrCopii;
      vecinHeavy = vecin;
    }
  }

  for(int i = 0; i < arb[node].edge.size(); i++) {
    vecin = arb[node].edge[i];
    if(vecin == p) {
      continue;
    }
    if(vecin != vecinHeavy) {
      pLight[arb[vecin].grupa] = node;
      pozStartAint[arb[vecin].grupa] = aintGlobal + pozStartCur;
      pozStartCur += arb[vecin].ordNumber * 4;
    } else {
      arb[node].grupa = arb[vecin].grupa;
      arb[node].ordNumber = arb[vecin].ordNumber + 1;
      sizeOfGrupa[arb[node].grupa]++;
    }
  }
  return totalCopii;
}

int query(int* aint, int p, int lInt, int rInt, int lTarget, int rTarget) {
    if(lTarget <= lInt && rInt <= rTarget) {
        return aint[p];
    }

    int med = (lInt + rInt) / 2, mx = 0;

    if(lTarget <= med) {
        mx = max(mx, query(aint, p * 2, lInt, med, lTarget, rTarget));
    }
    if(med + 1 <= rTarget) {
        mx = max(mx, query(aint, p * 2 + 1, med + 1, rInt, lTarget, rTarget));
    }

    return mx;
}

void update(int* aint, int p, int lInt, int rInt, int target, int val) {
    if(lInt == rInt) {
        aint[p] = val;
        return;
    }

    int med = (lInt + rInt) / 2;

    if(target <= med) {
        update(aint, p * 2, lInt, med, target, val);
    }
    if(med + 1 <= target) {
        update(aint, p * 2 + 1, med + 1, rInt, target, val);
    }
    aint[p] = max(aint[p * 2], aint[p * 2 + 1]);
}

int main() {
  int n, m, i, a, b, c;
  cin>>n>>m;
  for(i = 1; i <= n; i++) {
    cin>>v[i];
  }
  for(i = 1; i < n; i++) {
    cin>>a>>b;
    arb[a].edge.push_back(b);
    arb[b].edge.push_back(a);
  }
  arb[1].depth = 1;
  dfs(1, 0);
  pozStartAint[arb[1].grupa] = &aintGlobal[pozStartCur];
  pozStartCur += arb[1].ordNumber * 4;
  for(i = 1; i <= n; i++) {
    update(pozStartAint[arb[i].grupa], 1, 1, sizeOfGrupa[arb[i].grupa], arb[i].ordNumber, v[i]);
  }
  for(i = 1; i <= m; i++) {
    cin>>c>>a>>b;
    if(c == 0) {
        update(pozStartAint[arb[a].grupa], 1, 1, sizeOfGrupa[arb[a].grupa], arb[a].ordNumber, b);
    } else {
        int josa = arb[a].ordNumber, susa = sizeOfGrupa[arb[a].grupa], josb = arb[b].ordNumber, susb = sizeOfGrupa[arb[b].grupa], mx = 0;
        while(arb[a].grupa != arb[b].grupa) {
            if(arb[pLight[arb[a].grupa]].depth >= arb[pLight[arb[b].grupa]].depth) {
                mx = max(mx, query(pozStartAint[arb[a].grupa], 1, 1, sizeOfGrupa[arb[a].grupa], josa, susa));
                a = pLight[arb[a].grupa];
                josa = arb[a].ordNumber;
                susa = sizeOfGrupa[arb[a].grupa];
            } else {
                mx = max(mx, query(pozStartAint[arb[b].grupa], 1, 1, sizeOfGrupa[arb[b].grupa], josb, susb));
                b = pLight[arb[b].grupa];
                josb = arb[b].ordNumber;
                susb = sizeOfGrupa[arb[b].grupa];
            }
        }
        mx = max(mx, query(pozStartAint[arb[a].grupa], 1, 1, sizeOfGrupa[arb[a].grupa], min(arb[a].ordNumber, arb[b].ordNumber), max(arb[a].ordNumber, arb[b].ordNumber)));
        cout<<mx<<"\n";
    }
  }
  return 0;
}