Cod sursa(job #608816)

Utilizator GavrilaVladGavrila Vlad GavrilaVlad Data 18 august 2011 12:37:09
Problema Heavy Path Decomposition Scor Ascuns
Compilator cpp Status done
Runda Marime 3.9 kb
#pragma comment(linker, "/STACK:16777216")
#include<stdio.h>
#include<vector>
#include<cstdlib>

using namespace std;

#define x first
#define y second
#define pb push_back
#define lg 100005

int VALUES[lg], n, m, i, j, k, x, y, nod, val, nod1, nod2, ind, ll, p1, p2, pt[21], lvl, mm, posk, pz, nr = 1, *qq[lg], *fnd[lg], sol, lca, poslca[lg], wh[lg], pos[lg], prt[lg];
bool fst[lg];
char ch;
vector<int> v[lg], dt[lg];
pair<int, int> q[lg], llca[18][2*lg+5];

void df(int nod, int ad){
	ind ++;
	q[nod].x = ind; fst[nod] = 1;

	++ll; llca[0][ll].x = ad, llca[0][ll].y = nod; poslca[nod] = ll;

	for (int i = 0; i < (int)v[nod].size(); i ++)
		if (!fst[v[nod][i]]){
			df(v[nod][i], ad+1);

			++ll; llca[0][ll].x = ad, llca[0][ll].y = nod;
		}
	q[nod].y = ind;
}
void dfs(int nod){
	dt[nr].pb(nod); wh[nod] = nr, pos[nod] = dt[nr].size() - 1;
	mm = -1, posk = -1;

	for (int i = 0; i < (int)v[nod].size(); i ++)
		if (!wh[v[nod][i]])
			if (q[v[nod][i]].y - q[v[nod][i]].x > mm)
				mm = q[v[nod][i]].y - q[v[nod][i]].x, posk = i;

	if (posk == -1)
		return ;
	dfs(v[nod][posk]);
	for (int i = 0; i < (int)v[nod].size(); i ++)
		if (!wh[v[nod][i]]){
			nr ++;
			prt[nr] = nod;
			dfs(v[nod][i]);
		}
}
void cstr(int pz, int st, int dr, int poz){
	if (st == dr){
		fnd[pz][st] = poz;

		return ;
	}

	int x = (st + dr) / 2;

	cstr(pz, st, x, 2*poz);
	cstr(pz, x+1, dr, 2*poz+1);
}
void query(int pz, int st, int dr, int poz){
	if (st >= p1 && dr <= p2){
		sol = max(sol, qq[pz][poz]);
		return ;
	}
	if (dr < p1 || st > p2 || st == dr)
		return ;

	int x = (st + dr) / 2;

	query(pz, st, x, 2*poz);
	query(pz, x+1, dr, 2*poz+1);
}

int caut(int x, int y){
	int rz = qq[wh[x]][fnd[ wh[x] ][ pos[x] ]];

	while (x != y){
		if (wh[x] == wh[y]){
			p1 = pos[x], p2 = pos[y];

			sol = 0; query(wh[x], 0, dt[wh[x]].size() - 1, 1);
			rz = max(rz, sol);

			x = y;
		}
		else{
			p1 = 0, p2 = pos[y];

			sol = 0; query(wh[y], 0, dt[wh[y]].size() - 1, 1);
			rz = max(rz, sol);

			y = prt[wh[y]];
		}
	}

	return rz;
}

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

	scanf("%d", &n);
	for (i = 1; i < n; i ++){
		scanf("%d%d", &x, &y);

		v[x].pb(y), v[y].pb(x);
	}

	for(i=1; i<=n; ++i)
        scanf("%d", &VALUES[i]);


	df(1, 0);

	dfs(1);

	for (i = 1; i <= nr; i ++){
		for (k = 1; 2 * dt[i].size() > k; k *= 2);

		qq[i] = (int*)realloc(qq[i], (k + 1) * sizeof(int));

		for (j = 0; j <= k; j ++)
			qq[i][j] = 0;

		fnd[i] = (int*)realloc(fnd[i], (dt[i].size() + 1) * sizeof(int));

		cstr(i, 0, dt[i].size() - 1, 1);
	}

	pt[0] = 1;
	for (i = 1; i <= 20; i ++)
		pt[i] = 2*pt[i-1];

	for (i = 1; pt[i] <= ll; i ++)
		for (j = 1; j + pt[i] - 1 <= ll; j ++)
			if (llca[i-1][j].x < llca[i-1][j + pt[i-1]].x)
				llca[i][j] = llca[i-1][j];
			else
				llca[i][j] = llca[i-1][j + pt[i-1]];


	scanf("%d", &m);

	for(i=1; i<=n; ++i)
    {
        nod=i;
        val=VALUES[i];
        lvl = wh[nod]; pz = fnd[lvl][ pos[nod] ]; //printf("%d\n", pz);
        qq[lvl][pz] += val; pz /= 2;

        for (; pz != 0; pz /= 2)
            qq[lvl][pz] = max(qq[lvl][2*pz], qq[lvl][2*pz+1]);
    }

	for (i = 1; i <= m; i ++){
		scanf("%d", &ch);

		if (ch == 0){
			scanf("%d%d", &nod, &val);

			lvl = wh[nod]; pz = fnd[lvl][ pos[nod] ]; //printf("%d\n", pz);
			qq[lvl][pz] += val; pz /= 2;

			for (; pz != 0; pz /= 2)
				qq[lvl][pz] = max(qq[lvl][2*pz], qq[lvl][2*pz+1]);
			/*
			 for (j = 1; j < 3*dt[lvl].size(); j ++)
			 printf("%d ", qq[lvl][j]);
			 printf("\n");
			 */
		}
		else{
			scanf("%d%d", &nod1, &nod2);

			p1 = poslca[nod1], p2 = poslca[nod2];
			if (p1 > p2)
				swap(p1, p2);

			int lnd = p2 - p1 + 1;
			for (j = 0; pt[j] <= lnd; j ++); j --;

			if (llca[j][p1].x < llca[j][p2 - pt[j] + 1].x)
				lca = llca[j][p1].y;
			else
				lca = llca[j][p2 - pt[j] + 1].y;

			//printf("lca intre %d %d  %d\n", nod1, nod2, lca);

			printf("%d\n", max( caut(lca, nod1), caut(lca, nod2) ));
		}
	}

	return 0;
}