Cod sursa(job #1567937)

Utilizator TimitocArdelean Andrei Timotei Timitoc Data 13 ianuarie 2016 20:25:07
Problema Heavy Path Decomposition Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 4.18 kb
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#define MAXN 100100

using namespace std;

struct nod
{
    int val, parent, lant, depth, lpos;
};
struct lt
{
    vector<int> elem;
    int parentNod;
};
nod noduri[MAXN];
lt lanturi[MAXN];
vector<int> arb[MAXN];
vector<int> arbi[MAXN];
int n, m, nq; /// nq = numarul de lanturi

void citire()
{
	int x, y;
	scanf("%d %d", &n, &m);
	for (int i = 1; i <= n; i++)
		scanf("%d ", &noduri[i].val);
	for (int i = 1; i <= n-1; i++) {
		scanf("%d %d", &x, &y);
		arb[x].push_back(y);
	}
}
/// Returns weight of the subtree
int dfs (int crt, int nivel)
{
	int w = 0;
	noduri[crt].depth = nivel;
    int maxi = -1, pos;
	for (int i = 0, t = arb[crt].size(); i < t; i++)
	{
        int y = arb[crt][i];
        if (noduri[crt].parent == y) continue;
        noduri[y].parent = crt;
        int nw = dfs(y, nivel+1);
		if (nw > maxi) {
			maxi = nw;
			pos = y;
		}
		w += nw;
	}
	if (arb[crt].size()) {
		for (int i = 0, t = arb[crt].size(); i < t; i++)
			if (arb[crt][i] != pos)
				lanturi[noduri[arb[crt][i]].lant].parentNod = crt;
		lanturi[noduri[pos].lant].elem.push_back(crt);
		noduri[crt].lant = noduri[pos].lant;
	}
    else {
		lanturi[++nq].elem.push_back(crt);
		noduri[crt].lant = nq;
    }
    return w+1;
}

void update(vector<int> v, vector<int> &arib, int crt, int st, int fn, int newValue, int pos)
{
	if (st == fn) {
		arib[crt] = newValue;
		return;
	}
	int mid = (st+fn)/2;
	if (pos <= mid)
		update(v, arib, 2*crt, st, mid, newValue, pos);
	else
		update(v, arib, 2*crt+1, mid+1, fn, newValue, pos);
    arib[crt] = max(arib[2*crt], arib[2*crt+1]);
}

void arbInt(vector<int> v, int ind)
{
	arbi[ind].resize(4*v.size());
	for (int i = 0, t = v.size(); i < t; i++) {
        update(v, arbi[ind], 1, 0, v.size()-1, noduri[v[i]].val, noduri[v[i]].lpos);
	}
}

int query(vector<int> v, vector<int> arib, int crt, int st, int fn, int qs, int qf)
{
    if (qs <= st && qf >= fn)
		return arib[crt];
    int mid = (st+fn)/2;
    if (qf <= mid)
		return query(v, arib, 2*crt, st, mid, qs, qf);
	if (qs >= mid+1)
		return query(v, arib, 2*crt+1, mid+1, fn, qs, qf);
	else return max(query(v, arib, 2*crt, st, mid, qs, qf),
					query(v, arib, 2*crt+1, mid+1, fn, qs, qf));
}

void prepare()
{
    dfs(1, 0) == n;
    ///Debug
//    for (int i = 1; i <= nq; i++) {
//        printf("\nParent is: %d\n\tVector is: ", lanturi[i].parentNod);
//        for (int j = 0; j < lanturi[i].elem.size(); j++)
//			printf("%d ", lanturi[i].elem[j]);
//    }
	for (int i = 1; i <= nq; i++)
		reverse(lanturi[i].elem.begin(), lanturi[i].elem.end());
	for (int i = 1; i <= nq; i++) {
		for (int j = 0, t = lanturi[i].elem.size(); j < t; j++)
			noduri[lanturi[i].elem[j]].lpos = j;
		arbInt(lanturi[i].elem, i);
	}
	lanturi[noduri[1].lant].parentNod = n+5;
	noduri[n+5].depth = -1;
}

int solve(int x, int y)
{
	int i = x, j = y, maxim = -1;
	i = x; j = y;
    while (true)
	{
        if (noduri[i].lant == noduri[j].lant) {
			int st = min(noduri[i].lpos, noduri[j].lpos);
			int fn = max(noduri[i].lpos, noduri[j].lpos);
			maxim = max(maxim, query(lanturi[noduri[i].lant].elem, arbi[noduri[i].lant], 1,
										0, lanturi[noduri[i].lant].elem.size()-1, st, fn));
			break;
        }
        else {
			int d1 = noduri[lanturi[noduri[i].lant].parentNod].depth;
			int d2 = noduri[lanturi[noduri[j].lant].parentNod].depth;
			if (d1 > d2) {
				maxim = max(maxim, query(lanturi[noduri[i].lant].elem, arbi[noduri[i].lant], 1,
											0, lanturi[noduri[i].lant].elem.size()-1, 0, noduri[i].lpos));
				i = lanturi[noduri[i].lant].parentNod;
			}
			else {
				maxim = max(maxim, query(lanturi[noduri[j].lant].elem, arbi[noduri[j].lant], 1,
											0, lanturi[noduri[j].lant].elem.size()-1, 0, noduri[j].lpos));
				j = lanturi[noduri[j].lant].parentNod;
			}
        }
	}
	return maxim;
}

int main()
{
    freopen("heavypath.in", "r", stdin);
    freopen("heavypath.out", "w", stdout);

	int t, x, y;
	citire();
	prepare();
	for (int i = 1; i <= m; i++) {
        scanf("%d %d %d", &t, &x, &y);
        if (t == 0)
			update(lanturi[noduri[x].lant].elem, arbi[noduri[x].lant],
					1, 0, lanturi[noduri[x].lant].elem.size()-1, y, noduri[x].lpos);
		else
			printf("%d\n", solve(x, y));
	}

    return 0;
}