Cod sursa(job #657697)

Utilizator claudiumihailClaudiu Mihail claudiumihail Data 7 ianuarie 2012 08:24:51
Problema Arbori de intervale Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.85 kb
#include <fstream>
#include <iostream>
#include <limits>

#define MAX_SIZE 100001
#define GET_0_BASED_INDEX_PARENT(index) (((index)-1-!((index)%2)) / 2)

using namespace std;

int intervalSize;
int intervalTree[4*MAX_SIZE+1];

void Update(const int index, const int val)
{
	int left = 0, right = intervalSize-1;
	int intervalTreeIndex = 0;
	
	while (left < right)
	{
		const int mid = left + (right-left)/2;
		if (index <= mid)
		{
			//cout << index << " <= " << mid << endl;
			intervalTreeIndex = 2*intervalTreeIndex + 1;
			right = mid;
		}
		else
		{
			//cout << index << " > " << mid << endl;
			intervalTreeIndex = 2*(intervalTreeIndex+1);
			left = mid+1;
		}
	}
	
	if (left == index)
	{
		intervalTree[intervalTreeIndex] = val;
		//cout << "yes\n";
		
		int parent = GET_0_BASED_INDEX_PARENT(intervalTreeIndex);
		
		while(parent >= 0)
		{
			intervalTree[parent] = max(intervalTree[2*parent+1], intervalTree[2*(parent+1)]);
			intervalTreeIndex = parent;
			parent = GET_0_BASED_INDEX_PARENT(intervalTreeIndex);
		}
	}
}

int QueryElementaryInterval(const int index)
{
	int left = 0, right = intervalSize-1;
	int intervalTreeIndex = 0;
	
	while (left < right)
	{
		const int mid = left + (right-left)/2;
		if (index <= mid)
		{
			//cout << index << " <= " << mid << endl;
			intervalTreeIndex = 2*intervalTreeIndex + 1;
			right = mid;
		}
		else
		{
			//cout << index << " > " << mid << endl;
			intervalTreeIndex = 2*(intervalTreeIndex+1);
			left = mid+1;
		}
	}
	
	if (left == index)
	{
		return intervalTree[intervalTreeIndex];
	}
	
	return -1;
}

int QueryLeftSubInterval(int left, int right, const int finalLeft, int intervalTreeIndex)
{
	int maximum = numeric_limits<int>::min();
	
	while (1)
	{
		const int mid = left + (right-left)/2;
		
		if (finalLeft == left)
		{
			//intervalTreeIndex = 2*(intervalTreeIndex+1);
			maximum = max(maximum, intervalTree[intervalTreeIndex]);
			break;
		}
		else if (finalLeft <= mid)
		{
			maximum = max(maximum, intervalTree[2*(intervalTreeIndex+1)]);
			intervalTreeIndex = 2*intervalTreeIndex+1;
			right = mid;
		}
		else
		{
			left = mid+1;
			intervalTreeIndex = 2*(intervalTreeIndex+1);
		}
	}
	
	return maximum;
}

int QueryRightSubInterval(int left, int right, const int finalRight, int intervalTreeIndex)
{	
	int maximum = numeric_limits<int>::min();
	
	while (1)
	{
		const int mid = left + (right-left)/2;

		if (finalRight == right)
		{
			//intervalTreeIndex = 2*intervalTreeIndex+1;
			maximum = max(maximum, intervalTree[intervalTreeIndex]);
			break;
		}
		else if (finalRight > mid)
		{
			maximum = max(maximum, intervalTree[2*intervalTreeIndex+1]);
			intervalTreeIndex = 2*(intervalTreeIndex+1);
			left = mid+1;
		}
		else
		{
			right = mid;
			intervalTreeIndex = 2*intervalTreeIndex+1;
		}
	}
	
	return maximum;
}

int Query(const int l, const int r)
{
	int maximum = 0;
	int intervalTreeIndex = 0;
	int left = 0, right = intervalSize-1;
	
	if (l == r)
	{
		return QueryElementaryInterval(l);
	}

	int mid = left + (right-left)/2;
	while (r <= mid || l > mid)
	{
		if (r <= mid)
		{
			right = mid;
			intervalTreeIndex = 2*intervalTreeIndex+1;
		}
		else if (l > mid)
		{
			left = mid+1;
			intervalTreeIndex = 2*(intervalTreeIndex+1);
		}
		
		mid = left + (right-left)/2;
		
		//cout << l << " " << r << " included in " << left << " " << right << endl;
	}
	
	//cout << "Left = " << left << endl;
	//cout << "Right = " << right << endl;
	
	/*cout << QueryLeftSubInterval(left, mid, 2*intervalTreeIndex+1) << endl;
	cout << QueryRightSubInterval(mid+1, right, 2*(intervalTreeIndex+1)) << endl;*/
	
	//cout << "Mid = " << mid << endl;
	
	maximum = max(QueryLeftSubInterval(left, mid, l, 2*intervalTreeIndex+1),
				QueryRightSubInterval(mid+1, right, r, 2*(intervalTreeIndex+1)));
	
	return maximum;
}

int main()
{
	int m;
	fstream fin("arbint.in", fstream::in);
	fstream fout("arbint.out", fstream::out);
	
	fin >> intervalSize >> m;
	//cout << intervalSize << " " << m << endl << endl;

	for (int i=0; i<intervalSize; ++i)
	{
		int x;
		fin >> x;
		//cout << x << " ";
		Update(i,x);
	}
	//cout << endl;
	
	for (int i=0; i<m; ++i)
	{
		int opt, a, b;
		fin >> opt >> a >> b;
		
		switch (opt)
		{
			case 0:
			{
				//cout << opt << " " << a-1 << " " << b-1 << endl;
				fout << Query(a-1,b-1) << "\n";
			}; break;
			
			case 1:
			{
				//cout << opt << " " << a-1 << " " << b << endl;
				Update(a-1,b);
			}; break;
		}
	}
	/*intervalSize = 5;

	Update(0,4);
	Update(1,3);
	Update(2,2);
	Update(3,6);
	Update(4,1);
	
	for (int i=0; i<4*intervalSize+1; ++i)
	{
		cout << intervalTree[i] << " ";
	}
	cout << endl;
	
	cout << Query(1,2) << endl;
	
	cout << Query(4,4) << endl;*/
	
	//fin.close();
	//fout.close();
	
	return 0;
}