Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <fstream>
- #include <vector>
- const int MAXN = 1e5 + 5;
- using namespace std;
- ifstream in("heavypath.in");
- ofstream out("heavypath.out");
- /// nod_lant[i] = in ce lant se afla nodul i
- /// pozitie[i] = pe ce pozitie se afla in lantul (deja stiut) nodul i
- /// inaltime[i] = care este inaltimea lantului care se afla pe pozitia i
- /// daca am lantul pe ex : 4 3 2 1(e luat de la spate in fata din cauza la dfs)
- /// atunci nod_lant[4] = nod_lant[3] = nod_lant[2] = nod_lant[1] = 1 primul lant
- /// pozitie[4] = 1 in lant se alfa pe poz 1, pozitie[3] = 2, pozitie[2] = 3, pozitie[1] = 4
- /// inaltime[1] = 1, se afla la inaltimea 1, dar lantul 9 8 7 se afla la inaltimea 2
- /// daca citeste cineva asta sper sa inteleaga :)
- /// singurul vector indexat de la 0 este lant[i]
- int tata[MAXN],dimensiune[MAXN],nod_lant[MAXN],pozitie[MAXN],inaltime[MAXN];
- int valori[MAXN];
- bool viz[MAXN];
- int nr_lanturi;
- vector<int>arbore_intervale[MAXN];/// Sunt indexati de la 1!!!!!
- vector<int>lant[MAXN];/// indexati de la 0!!
- vector<int>graf[MAXN];
- void dfs(int nod,int anterior = -1){
- dimensiune[nod] = 1;
- viz[nod] = true;
- int curent;
- for(int i = 0; i < graf[nod].size(); i++){
- curent = graf[nod][i];
- if(curent == anterior){
- /// anteriorul este nodul care a fost parcurs inainte
- /// daca eu vreau sa ma duc cu o muchie in spate atunci tatal nodului curent este anterior
- tata[nod] = anterior;
- }
- if(!viz[curent]){
- dfs(curent,nod);
- dimensiune[nod] += dimensiune[curent];
- }
- }
- if(graf[nod].size() == 1 && nod != 1){
- lant[++nr_lanturi].push_back(nod);
- nod_lant[nod] = nr_lanturi;
- pozitie[nod] = 1; /// il pun pe pozitia 1
- }else{
- int vecin_bun,maxim = 0;
- for(int i = 0; i < graf[nod].size(); i++){
- int curent = graf[nod][i];
- if(dimensiune[curent] > maxim && curent != anterior){
- vecin_bun = curent;
- maxim = dimensiune[curent];
- }
- }
- int unde = nod_lant[vecin_bun];
- lant[unde].push_back(nod); /// adaug nodul nod la lantul cu subarborele maxim
- nod_lant[nod] = unde;
- pozitie[nod] = lant[unde].size();/// il pun pe ultima pozitie
- for(int i = 0; i < graf[nod].size(); i++){
- int curent = graf[nod][i];
- if(nod_lant[curent] != nod_lant[nod])
- ///Vlad: Modifici inaltimea lantului unui fiu fara sa ai calculata inaltimea lantului nodului
- inaltime[nod_lant[curent]] = inaltime[nod_lant[nod]] + 1; /// modific inaltimea lantului
- }
- }
- }
- void update(int index_lant,int val,int pozitie,int st,int dr,int nod = 1){
- ///cout<<st<<" "<<dr<<" "<<pozitie<<" "<<nod<<endl;
- if(st == dr && st == pozitie){
- arbore_intervale[index_lant][nod] = val;
- return;
- }
- int mij = (st + dr) / 2;
- if(pozitie <= mij)
- update(index_lant,val,pozitie,st,mij,nod * 2);
- else
- update(index_lant,val,pozitie,mij + 1,dr,nod * 2 + 1);
- if(nod * 2 + 1 < arbore_intervale[index_lant].size()) /// sa nu cumva sa ies din size
- arbore_intervale[index_lant][nod] = max(arbore_intervale[index_lant][nod * 2],arbore_intervale[index_lant][nod * 2 + 1]);
- }
- int query(int index_lant,int query_left,int query_right,int st,int dr,int nod = 1){
- ///cout<<st<<" "<<dr<<" "<<nod<<" "<<arbore_intervale[index_lant][nod]<<endl;
- if(query_left <= st && dr <= query_right)
- return arbore_intervale[index_lant][nod];
- int mij = (st + dr) / 2;
- int val_stanga = 0,val_dreapta = 0;
- if(query_left <= mij)
- val_stanga = query(index_lant,query_left,query_right,st,mij,nod * 2);
- if(mij + 1 <= query_right)
- val_dreapta = query(index_lant,query_left,query_right,mij + 1,dr,nod * 2 + 1);
- return max(val_stanga,val_dreapta);
- }
- int query_lant(int nod){
- int index_lant = nod_lant[nod];
- int dimensiune = lant[index_lant].size();
- int poz = pozitie[nod];/// pozitie e de la 1 indexat
- return query(index_lant,poz,dimensiune,1,dimensiune);
- }
- int intrebare(int a,int b){
- /// calculez usor usor lca intre a si b
- if(inaltime[nod_lant[a]] < inaltime[nod_lant[b]])
- swap(a,b);
- /// a este intr-un lant mai sus decat b
- int maxim = max(query_lant(a),query_lant(b)); ///Vlad: nu garanteaza nimic ca a este intr-un lant mai sus decat b. pot fi foarte bine pe acelasi lant.
- while(inaltime[nod_lant[a]] > inaltime[nod_lant[b]]){
- int urmatorul = lant[nod_lant[a]].back();/// ultimul element
- a = tata[urmatorul];
- maxim = max(maxim,query_lant(a));
- }
- /// sunt pe aceasi inaltime
- while(nod_lant[a] != nod_lant[b]){
- int urmatorul = lant[nod_lant[a]].back();
- a = tata[urmatorul];
- maxim = max(maxim,query_lant(a));
- urmatorul = lant[nod_lant[b]].back();
- b = tata[urmatorul];
- maxim = max(maxim,query_lant(b));
- }
- /// sunt in acelasi lant
- /// eu vreau ca a sa fie mai jos pe lant
- /// vectorul de pozitii este pe invers adica pt lantul 4 3 2 1, poz : 1 2 3 4
- /// vreau ca poz[a] < poz[b] daca nu, fac este swap(a,b)
- ///cout<<a<<" "<<b<<" "<<" pozitii : "<<pozitie[a]<<" "<<pozitie[b]<<endl;
- if(pozitie[a] > pozitie[b])
- swap(a,b);
- int query_pe_lant = query(nod_lant[a],pozitie[a],pozitie[b],1,lant[nod_lant[a]].size());
- maxim = max(maxim,query_pe_lant);
- /// acum stiu clar ca a = b;
- out<<maxim<<"\n";
- }
- void construieste_arbore(int index_lant){
- vector<int>arbore(4 * lant[index_lant].size() + 2);
- arbore_intervale[index_lant] = arbore;
- int lung_lant = lant[index_lant].size();
- for(int i = 0; i < lant[index_lant].size(); i++){
- int val = valori[lant[index_lant][i]];
- update(index_lant,val,i + 1,1,lung_lant);/// !! indexati de la 1 de aia poz = i + 1
- }
- }
- int main()
- {
- int n,intrebari;
- in>>n>>intrebari;
- for(int i = 1; i <= n; i++)
- in>>valori[i];
- for(int i = 1; i <= n - 1; i++){
- int x,y;
- in>>x>>y;
- graf[x].push_back(y);
- graf[y].push_back(x);
- }
- inaltime[1] = 1;
- dfs(1);
- for(int i = 1; i <= n; i++)
- construieste_arbore(i);
- for(int i = 1; i <= intrebari; i++){
- int cerinta,a,b;
- in>>cerinta>>a>>b;
- if(cerinta == 1){
- intrebare(a,b);
- }else{
- int index_lant = nod_lant[a];
- int pozitie_lant = pozitie[a];
- update(index_lant,b,pozitie_lant,1,lant[index_lant].size());
- }
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement