Cod sursa(job #658389)

Utilizator claudiumihailClaudiu Mihail claudiumihail Data 8 ianuarie 2012 19:00:26
Problema Arbori de intervale Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.94 kb
#include <fstream>
#include <iostream>
#include <limits>

#define MAX_SIZE 100001
#define GET_0_BASED_INDEX_PARENT(index) (((index)-1-!((index)%2)) / 2)
#define LEFT_SUBTREE(index) (((index)<<1)+1)
#define RIGHT_SUBTREE(index) (((index)+1)<<1)

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)
		{
			intervalTreeIndex = LEFT_SUBTREE(intervalTreeIndex);
			right = mid;
		}
		else
		{
			intervalTreeIndex = RIGHT_SUBTREE(intervalTreeIndex);
			left = mid+1;
		}
	}
	
	if (left == index)
	{
		intervalTree[intervalTreeIndex] = val;
		
		int parent = GET_0_BASED_INDEX_PARENT(intervalTreeIndex);
		
		while(parent >= 0)
		{
			intervalTree[parent] = max(intervalTree[LEFT_SUBTREE(parent)], intervalTree[RIGHT_SUBTREE(parent)]);
			intervalTreeIndex = parent;
			parent = GET_0_BASED_INDEX_PARENT(intervalTreeIndex);
		}
	}
}

inline static 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)
		{
			intervalTreeIndex = LEFT_SUBTREE(intervalTreeIndex);
			right = mid;
		}
		else
		{
			intervalTreeIndex = RIGHT_SUBTREE(intervalTreeIndex);
			left = mid+1;
		}
	}
	
	if (left == index)
	{
		return intervalTree[intervalTreeIndex];
	}
	
	return -1;
}

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

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

		if (finalRight > mid)
		{
			maximum = max(maximum, intervalTree[LEFT_SUBTREE(intervalTreeIndex)]);
			intervalTreeIndex = RIGHT_SUBTREE(intervalTreeIndex);
			left = mid+1;
		}
		else
		{
			right = mid;
			intervalTreeIndex = LEFT_SUBTREE(intervalTreeIndex);
		}
	}
	
	maximum = max(maximum, intervalTree[intervalTreeIndex]);
	
	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 = LEFT_SUBTREE(intervalTreeIndex);
		}
		else if (l > mid)
		{
			left = mid+1;
			intervalTreeIndex = RIGHT_SUBTREE(intervalTreeIndex);
		}
		
		mid = left + (right-left)/2;
	}
	
	maximum = max(QueryLeftSubInterval(left, mid, l, LEFT_SUBTREE(intervalTreeIndex)),
				QueryRightSubInterval(mid+1, right, r, RIGHT_SUBTREE(intervalTreeIndex)));
	
	return maximum;
}

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

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