Cod sursa(job #2663965)

Utilizator Iulia25Hosu Iulia Iulia25 Data 27 octombrie 2020 18:02:29
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.91 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>

using namespace std;

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

const int MAXN = 1e5 + 5;

int n, k;
int subarb[MAXN], val[MAXN];
int poz[MAXN]; ///pozitia nodului i din arbore in aint
int adancime[MAXN];
int tata[MAXN][20];

vector <int> vecin[MAXN];

struct aint  {
  int nod, lant;
} a[4 * MAXN];

bool cmp_vecini(int x, int y)  {
	return subarb[x] > subarb[y];
}

void dfs(int nod)  {
	subarb[nod] = 1;
	for (auto it : vecin[nod])  {
		if (!subarb[it])  {
			adancime[it] = adancime[nod] + 1;
			tata[it][0] = nod;
			dfs(it);
			subarb[nod] += subarb[it];
		}
	}
}

void Update_aint(int nod)  {
  if (val[a[nod + nod].nod] > val[a[nod + nod + 1].nod])
    a[nod].nod = a[nod + nod].nod;
  else a[nod].nod = a[nod + nod + 1].nod;
	if (nod > 1)
		Update_aint(nod / 2);
}

int Query_aint(int st, int dr)  {
	int ans = 0;
	if (st & 1)
		ans = val[a[st++].nod];
	if (!(dr & 1))  {
		ans = max(ans, val[a[dr].nod]);
		--dr;
	}
	if (st > dr)
		return ans;
	int aux = Query_aint(st / 2, dr / 2);
	return max(aux, ans);
}

void create_segments(int nod, int lant)  {
	a[++k] = {nod, lant};
	poz[nod] = k;
	Update_aint(k / 2);
	bool acelasi_lant = true;
	for (auto it : vecin[nod])  {
		if (it == tata[nod][0])
			continue;
		if (acelasi_lant)  {
			create_segments(it, lant);
			acelasi_lant = false;
		} else create_segments(it, it);
	}
}

void rmq()  {
	for (int i = 1; i < 20; ++i)  {
		for (int j = 1; j <= n; ++j)  {
			tata[j][i] = tata[tata[j][i - 1]][i - 1];
		}
	}
}

int find_tata(int nod, int nivel)  {
	for (int i = 1, j = 0; i <= nivel; i <<= 1, ++j)
		if (i & nivel)
			nod = tata[nod][j];
	return nod;
}

int lca(int x, int y)  {
	if (adancime[y] > adancime[x])
		swap(x, y);
	x = find_tata(x, adancime[x] - adancime[y]);
	if (x == y)
    return x;
	int ans = 1;
	for (int i = 19; i >= 0; --i)  {
		if (tata[x][i] == tata[y][i])
			ans = tata[x][i];
		else  {
			x = tata[x][i];
			y = tata[y][i];
		}
	}
	return ans;
}

int Query(int nod, int l)  {
  int st = poz[nod];
  int dr = max(poz[l], poz[a[st].lant]);
  int ans = Query_aint(dr, st);
  if (adancime[a[dr].lant] <= adancime[l])
    return ans;
  int aux = Query(tata[a[dr].lant][0], l);
  return max(aux, ans);
}

int main()  {
	int Q, nod1, nod2, start = 1;
	fin >> n >> Q;
	while (start < n)
		start <<= 1;
	for (int i = 1; i <= n; ++i)
		fin >> val[i];
	for (int i = 1; i < n; ++i)  {
		fin >> nod1 >> nod2;
		vecin[nod1].push_back(nod2);
		vecin[nod2].push_back(nod1);
	}
	adancime[1] = 1;
	dfs(1);
	rmq();
	for (int i = 1; i <= n; ++i)
		sort(vecin[i].begin(), vecin[i].end(), cmp_vecini);
	k = start - 1;
	create_segments(1, 1);
	int type, x, y;
	while (Q--)  {
		fin >> type >> x >> y;
		if (type == 0)  {
			val[x] = y;
			Update_aint(poz[x] / 2);
		} else  {
      int l = lca(x, y);
      int ans = Query(x, l);
      int aux = Query(y, l);
      fout << max(ans, aux) << '\n';
		}
	}
	return 0;
}