Cod sursa(job #3144567)

Utilizator NanuGrancea Alexandru Nanu Data 8 august 2023 21:15:14
Problema Heavy Path Decomposition Scor 60
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.83 kb
#include <fstream>
#include <vector>
using namespace std;

class InParser {
private:
	FILE *fin;
	char *buff;
	int sp;

	char read_ch() {
		++sp;
		if (sp == 4096) {
			sp = 0;
			fread(buff, 1, 4096, fin);
		}
		return buff[sp];
	}

public:
	InParser(const char* nume) {
		fin = fopen(nume, "r");
		buff = new char[4096]();
		sp = 4095;
	}
	
	InParser& operator >> (int &n) {
		char c;
		while (!isdigit(c = read_ch()) && c != '-');
		int sgn = 1;
		if (c == '-') {
			n = 0;
			sgn = -1;
		} else {
			n = c - '0';
		}
		while (isdigit(c = read_ch())) {
			n = 10 * n + c - '0';
		}
		n *= sgn;
		return *this;
	}
	
	InParser& operator >> (long long &n) {
		char c;
		n = 0;
		while (!isdigit(c = read_ch()) && c != '-');
		long long sgn = 1;
		if (c == '-') {
			n = 0;
			sgn = -1;
		} else {
			n = c - '0';
		}
		while (isdigit(c = read_ch())) {
			n = 10 * n + c - '0';
		}
		n *= sgn;
		return *this;
	}
};

#define DIM 100000

int n, q, lant, id;
int v[DIM + 5];
int w[DIM + 5];             //cati descendenti are nodul i.
int poz[DIM + 5];
int tata[DIM + 5];
int level[DIM + 5];
int chain[DIM + 5];         //din ce lant face parte nodul i;
int first[DIM + 5];         //primul nod din fiecare lant;
int Sonmax[DIM + 5];        //fiul care are cei mai multi descendenti.
int tree[4 * DIM + 5];  
int size_chain[DIM + 5];    //lungimea lantului actual.   
vector <int> G[DIM + 5];

static inline void Update_tree(int st, int dr, int nod, int poz, int val) {
  if(st == dr) 
    tree[nod] = val;
  else {
    int mid = (st + dr) >> 1;
    if(poz <= mid)
      Update_tree(st, mid, nod * 2, poz, val);
    else Update_tree(mid + 1, dr, nod * 2 + 1, poz, val);

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

static inline int Query_tree(int st, int dr, int nod, int left, int right) {
  if(left <= st && dr <= right)
    return tree[nod];

  int mid = (st + dr) >> 1;
  int max1 = 0, max2 = 0;

  if(left <= mid)
    max1 = Query_tree(st, mid, nod * 2, left, right);
  if(mid < right)
    max2 = Query_tree(mid + 1, dr, nod * 2 + 1, left, right);

  return max(max1, max2); 
}

static inline void dfs(int nod, int t) {
  tata[nod] = t;
  Sonmax[nod] = -1;
  w[nod] = 1;       //el insusi.
  level[nod] = level[t] + 1;

  for(auto e : G[nod])
    if(e != t) {
      dfs(e, nod);

      if(Sonmax[nod] == -1 || w[Sonmax[nod]] < w[Sonmax[e]])
        Sonmax[nod] = e;   //fiul care are cei mai multi descendenti.

      w[nod] += w[e];   
    }
}

static inline void Split(int nod) {
  chain[nod] = lant;
  poz[nod] = ++id;
  size_chain[lant]++;

  if(Sonmax[nod] == -1)   //daca e frunza;
    return;

  Split(Sonmax[nod]);

  for(auto e : G[nod]) 
    if(e != tata[nod] && e != Sonmax[nod]) {
      
      lant++;
      first[lant] = e;
      Split(e);
    }
}

static inline void Heavy_path() {
  dfs(1, 0);

  first[1] = 1;
  lant = 1;
  Split(1);

  for(int i = 1; i <= n; i++)
    Update_tree(1, n, 1, poz[i], v[i]);
}

static inline int Query(int x, int y) {
  if(chain[x] == chain[y])
    return Query_tree(1, n, 1, min(poz[x], poz[y]), max(poz[x], poz[y]));

  if(level[first[chain[x]]] < level[first[chain[y]]])
    swap(x, y);
  
  int ans = Query_tree(1, n, 1, poz[first[chain[x]]], poz[x]);  
  return max(ans, Query(tata[first[chain[x]]], y));
}

int main() {
  InParser fin("heavypath.in");
  ofstream fout("heavypath.out");
  fin >> n >> q;
  for(int i = 1; i <= n; i++) 
    fin >> v[i];

  for(int i = 1, x, y; i < n; i++) {
    fin >> x >> y;

    G[x].push_back(y);
    G[y].push_back(x);
  }

  Heavy_path();

  for(int i = 1, tip, x, y; i <= q; i++) {
    fin >> tip >> x >> y;

    if(tip == 0)  
      Update_tree(1, n, 1, poz[x], y);
    else fout << Query(x, y) << '\n';
  }

  return 0;
}