Cod sursa(job #2326845)

Utilizator SilviuIIon Silviu SilviuI Data 24 ianuarie 2019 09:35:47
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.46 kb
    #include <stdio.h>
    #include <vector>
    #include <algorithm>
    #include <math.h>
    #define nmax 100010
    #define SZ(x) ((int)(x.size()))
     
    using namespace std;
     
    int n, m, nr_chains;
    int val[nmax], dp[nmax], parent[nmax], depth[nmax];
    int nr_chain[nmax], pos_chain[nmax];
    vector <int> graph[nmax], chains[nmax], tree[nmax];
     
    void dfs(int node, int p = 0)
    {
    	dp[node] = 1;
     
    	for (int i = 0; i < SZ(graph[node]); i++)
    		if (graph[node][i] != p) {
     
    			depth[graph[node][i]] = depth[node] + 1;
     
    			dfs(graph[node][i], node);
     
    			parent[graph[node][i]] = node;
    			dp[node] += dp[graph[node][i]];
    		}
    }
     
    void buildLPD(int node, int chain, int p = 0)
    {
    	int mx = 0, indx = -1;
     
    	chains[chain].push_back(node);
     
    	nr_chain[node] = chain;
    	pos_chain[node] = chains[chain].size();
     
    	for (int i = 0; i < SZ(graph[node]); i++)
    		if (graph[node][i] != p && dp[graph[node][i]] > mx) {
     
    			indx = graph[node][i];
    			mx = dp[graph[node][i]];
    		}
     
    	if (indx != -1) buildLPD(indx, chain, node);
     
    	for (int i = 0; i < SZ(graph[node]); i++)
    		if (graph[node][i] != p && graph[node][i] != indx)  {
     
    			nr_chains++;
     
    			buildLPD(graph[node][i], nr_chains, node);
    		}
    }
     
    void build(int id, int node, int l, int r)
    {
    	if (l == r) {
     
    		tree[id][node] = val[chains[id][l - 1]];
     
    		return;
    	}
     
    	int m = (l + r) / 2;
     
    	build(id, node * 2, l, m);
    	build(id, node * 2 + 1, m + 1, r);
     
    	tree[id][node] = max(tree[id][node * 2], tree[id][node * 2 + 1]);
    }
     
    void buildTree(int chain)
    {
    	int tree_size = chains[chain].size();
     
    	tree[chain].resize(tree_size * 4);
     
    	build(chain, 1, 1, tree_size);
    }
     
    void update(int id, int node, int l, int r, int pos, int val)
    {
    	if (l == r) {
     
    		tree[id][node] = val;
     
    		return;
    	}
     
    	int m = (l + r) / 2;
     
    	if (pos <= m) update(id, node * 2, l, m, pos, val); else
    		update(id, node * 2 + 1, m + 1, r, pos, val);
     
    	tree[id][node] = max(tree[id][node * 2], tree[id][node * 2 + 1]);
    }
     
    int query(int id, int node, int l, int r, int ql, int qr)
    {
    	if (l >= ql && r <= qr) return tree[id][node]; 
     
    	int cur = -1;
    	int m = (l + r) / 2;
     
    	if (ql <= m) cur = max(cur, query(id, node * 2, l, m, ql, qr));
    	if (qr > m) cur = max(cur, query(id, node * 2 + 1, m + 1, r, ql, qr));
     
    	return cur;
    }
     
    int _query(int x, int y)
    {
    	int answer = -1;
    	
    	while (nr_chain[x] != nr_chain[y]) {
     
    		if (nr_chain[x] > nr_chain[y]) {
     
    			int chain = nr_chain[x];
    			int pos_inchain = pos_chain[x];
     
    			answer = max(answer, query(chain, 1, 1, chains[chain].size(), 1, pos_inchain));
     
    			x = parent[chains[chain][0]];
     
    		} else {
     
    			int chain = nr_chain[y];
    			int pos_inchain = pos_chain[y];
     
    			answer = max(answer, query(chain, 1, 1, chains[chain].size(), 1, pos_inchain));
     
    			y = parent[chains[chain][0]];
    		}
    	}
    	
    	int chain = nr_chain[x];
     
    	if (pos_chain[x] <= pos_chain[y]) answer = max(answer, query(chain, 1, 1, chains[chain].size(), pos_chain[x], pos_chain[y])); else
    		answer = max(answer, query(chain, 1, 1, chains[chain].size(), pos_chain[y], pos_chain[x]));
     
    	return answer;
    }
     
    int main()
    {
		freopen("heavypath.in", "r", stdin);
		freopen("heavypath.out", "w", stdout);
		
    	scanf("%d %d", &n, &m);
     
    	for (int i = 1; i <= n; i++) scanf("%d", &val[i]);
     
    	for (int i = 2; i <= n; i++) {
     
    		int x, y;
     
    		scanf("%d %d", &x, &y);
     
    		graph[x].push_back(y);
    		graph[y].push_back(x);
    	}
     
    	dfs(1);
     
    	nr_chains = 1;
     
    	buildLPD(1, 1);
     
    	for (int i = 1; i <= nr_chains; i++) buildTree(i);
     
    	for (int i = 1; i <= m; i++) {
     
    		int type, x, y;
     
    		scanf("%d %d %d", &type, &x, &y);
     
    		if (type == 0) update(nr_chain[x], 1, 1, chains[nr_chain[x]].size(), pos_chain[x], y); else
    			printf("%d\n", _query(x, y));
    	}
     
     	return 0;
    }