Cod sursa(job #989951)

Utilizator Cosmin1490Balan Radu Cosmin Cosmin1490 Data 26 august 2013 23:19:32
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 5.19 kb
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <fstream>
using namespace std;
  
const string file = "heavypath";
  
const string infile = file + ".in";
const string outfile = file + ".out";


int N, M;
vector<vector<int> > G;

vector<int> values;
vector<int> level;
vector<int> weight;


vector<vector<int> > Paths;
vector<int> pathParent;

vector<int> pathId;
vector<int> pathPos;


class SegmentTree
{
public:
	SegmentTree(int low, int hi);
	void Update(int low, int hi, int value);
	int Query(int low, int hi);
protected:
private:

	void Update(int nod, int st, int dr, int low, int hi, int value);
	int Query(int nod, int st, int dr, int low, int hi);

	int _low;
	int _hi;
	vector<int> _data;
};


SegmentTree::SegmentTree(int low, int hi)
{
	this->_low = low;
	this->_hi = hi;
	int size = hi - low + 1;
	int c = 1;
	while( c < size) c <<= 1;
	c <<= 1;

	this->_data.resize(c + 1);
}

void SegmentTree::Update(int low, int hi, int value)
{
	Update(1, _low, _hi, low, hi, value);
}

int SegmentTree::Query(int low, int hi)
{
	return Query(1, _low, _hi, low, hi);
}

void SegmentTree::Update(int nod, int st, int dr, int low, int hi, int value)
{
	if( low <= st && dr <= hi)
	{
		_data[nod] = value;
	}
	else
	{
		int mid = (st + dr) / 2;

		if(low <= mid)
			Update(nod * 2, st, mid, low, hi, value);
		if(mid < hi)
			Update(nod* 2 + 1, mid + 1, dr, low, hi, value);
		_data[nod] = max(_data[nod*2], _data[nod*2+1]);

	}
}

int SegmentTree::Query(int nod, int st, int dr, int low, int hi)
{
	if(low <= st && dr <= hi)
	{
		return _data[nod];
	}
	else
	{
		int result = 0;
		int mid = (st + dr)/2;
		if(low <= mid)
			result = max(result, Query(nod*2, st, mid, low, hi));
		if(mid < hi)
			result = max(result, Query(nod*2 + 1, mid + 1, dr, low, hi));
		return result;
	}
}


void dfs(int nod)
{

	
	stack<int> s;
	vector<bool> seen(N + 1);
	vector<bool> added(N + 1);

	s.push(nod);
	added[nod] = true;
	level[nod] = 0;

	while(s.empty() == false)
	{
		int current = s.top();
		if(seen[current] == false)
		{
			seen[current] = true;

			for(vector<int>::iterator itr = G[current].begin();
				itr != G[current].end();
				itr++)
			{
				if(added[*itr] == false)
				{
					added[*itr] = true;
					level[*itr] = level[current] + 1;
					s.push(*itr);
				}
			}
		}
		else
		{
			s.pop();
			int maxWeight =  0;
			for(vector<int>::iterator itr = G[current].begin();
				itr != G[current].end();
				itr++)
			{
				if(level[current] < level[*itr])
				{
					weight[current] += weight[*itr];
					if(weight[maxWeight] < weight[*itr])
						maxWeight = *itr;
				}
			}

			if(maxWeight == 0)
			{
				pathId[current] = Paths.size();
				pathPos[current] = 0;

				vector<int> newPath;
				newPath.push_back(current);
				pathParent.push_back(0);

				Paths.push_back(newPath);

			}
			else
			{
				pathId[current] = pathId[maxWeight];
				pathPos[current] = Paths[pathId[maxWeight]].size();
				Paths[pathId[maxWeight]].push_back(current);

				for(vector<int> :: iterator itr = G[current].begin();
					itr != G[current].end();
					itr++)
				{
					if(level[current] < level[*itr] && *itr != maxWeight)
					{
						pathParent[pathId[*itr]] = current;
					}
				}
			}
		}
	}
}



int main()
{
	fstream fin(infile.c_str(), ios::in);

	fin >> N >> M;
	G.resize(N + 1);
	values.resize(N + 1);
	for(int i = 0; i < N; i++)
	{
		fin >> values[i + 1];
		
	}

	for(int i = 1; i < N; i++)
	{
		int x, y;
		fin >> x >> y;
		G[x].push_back(y);
		G[y].push_back(x);
	}

	pathId.resize(N + 1, -1);
	pathPos.resize(N + 1, -1);

	weight.resize(N + 1, 1);
	weight[0] = 0;
	level.resize(N + 1);
	level[0] = -1;

	dfs(1);
	vector<SegmentTree> trees;
	for(unsigned i = 0; i < Paths.size(); i++)
	{
		trees.push_back(SegmentTree(0, Paths[i].size() - 1));
		for(unsigned j = 0; j < Paths[i].size(); j++)
		{
			trees[i].Update(j, j, values[Paths[i][j]]);
		}
	}

	fstream fout(outfile.c_str(), ios::out);

	for(int i = 0; i < M; i++)
	{
		int op, x, y;
		fin >> op >> x >> y;
		//cout << op << " " << x << " " << y << "\n";
		if(op == 0)
		{
			trees[pathId[x]].Update(pathPos[x], pathPos[x], y);
		}
		else if(op == 1)
		{
			int sol = 0;

			while(true)
			{
				if(pathId[x] == pathId[y])
				{
					sol = max(sol, trees[pathId[x]].Query(min(pathPos[x], pathPos[y]), max(pathPos[x], pathPos[y])));
					break;
				}

				if(level[pathParent[pathId[x]]] < level[pathParent[pathId[y]]])
					swap(x, y);

				sol = max(sol, trees[pathId[x]].Query(pathPos[x], Paths[pathId[x]].size() - 1));
				x = pathParent[pathId[x]];

			}
			//cout << sol << "\n";
			fout << sol << "\n";
		}
	}

	fin.close();
	fout.close();

}