Cod sursa(job #730316)

Utilizator claudiumihailClaudiu Mihail claudiumihail Data 6 aprilie 2012 04:13:08
Problema Arbori de intervale Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 5.78 kb
#include <fstream>
#include <iostream>
#include <limits>
#include <cstdlib>

#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;

typedef unsigned int uint32;

template<class T, class Compare = less<T> >
class IntervalTree
{
public:

	IntervalTree(const int size, const T& defaultValue)
	{
		intervalSize = size;
		vValues = (T*)malloc((size+1)*sizeof(T));
		vValues[size] = defaultValue;
		intervalTree = (int*)calloc((4*size+2), sizeof(int));
	}
	
	inline void Update(const int index, const T& value)
	{
		vValues[index] = value;
		UpdateIndex(index);
	}
	
	inline void Update(const int index)
	{
		UpdateIndex(index);
	}
	
	inline void UpdateIndex(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)
		{
			intervalTree[intervalTreeIndex] = index;
			
			int parent = GET_0_BASED_INDEX_PARENT(intervalTreeIndex);

			while(parent >= 0)
			{
				if (compare(vValues[intervalTree[LEFT_SUBTREE(parent)]], vValues[intervalTree[RIGHT_SUBTREE(parent)]]))
				{
					intervalTree[parent] = intervalTree[LEFT_SUBTREE(parent)];
				}
				else
				{
					intervalTree[parent] = intervalTree[RIGHT_SUBTREE(parent)];
				}
				
				intervalTreeIndex = parent;
				parent = GET_0_BASED_INDEX_PARENT(intervalTreeIndex);
			}
		}
	}

	inline int QueryIndex(const int l, const int r) const
	{
		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;
		}
		
		const int leftIndex = QueryLeftSubInterval(left, mid, l, LEFT_SUBTREE(intervalTreeIndex));
		const int rightIndex = QueryRightSubInterval(mid+1, right, r, RIGHT_SUBTREE(intervalTreeIndex));
		
		if (compare(vValues[leftIndex], vValues[rightIndex]))
		{
			return leftIndex;
		}

		return rightIndex;
	}
	
	inline T& QueryValue(const int l, const int r)
	{
		return vValues[QueryIndex(l,r)];
	}
	
	inline const T& QueryValue(const int l, const int r) const
	{
		return vValues[QueryIndex(l,r)];
	}

	inline T& GetValueAt(const int index)
	{
		return vValues[index];
	}
	
	inline const T& GetValueAt(const int index) const
	{
		return vValues[index];
	}

private:

	inline int QueryElementaryInterval(const int index) const
	{
		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 intervalTree[intervalSize];
	}

	inline int QueryLeftSubInterval(int left, int right, const int finalLeft, int intervalTreeIndex) const
	{
		int foundIndex = intervalSize;
		
		while (finalLeft != left)
		{
			const int mid = left + (right-left)/2;
			
			if (finalLeft <= mid)
			{
				if (compare(vValues[intervalTree[RIGHT_SUBTREE(intervalTreeIndex)]], vValues[foundIndex]))
				{
					foundIndex = intervalTree[RIGHT_SUBTREE(intervalTreeIndex)];
				}
				
				intervalTreeIndex = LEFT_SUBTREE(intervalTreeIndex);
				right = mid;
			}
			else
			{
				left = mid+1;
				intervalTreeIndex = RIGHT_SUBTREE(intervalTreeIndex);
			}
		}
		
		if (compare(vValues[intervalTree[intervalTreeIndex]], vValues[foundIndex]))
		{
			foundIndex = intervalTree[intervalTreeIndex];
		}
		
		return foundIndex;
	}

	inline int QueryRightSubInterval(int left, int right, const int finalRight, int intervalTreeIndex) const
	{	
		int foundIndex = intervalSize;
		
		while (finalRight != right)
		{
			const int mid = left + (right-left)/2;

			if (finalRight > mid)
			{
				if (compare(vValues[intervalTree[LEFT_SUBTREE(intervalTreeIndex)]], vValues[foundIndex]))
				{
					foundIndex = intervalTree[LEFT_SUBTREE(intervalTreeIndex)];
				}

				intervalTreeIndex = RIGHT_SUBTREE(intervalTreeIndex);
				left = mid+1;
			}
			else
			{
				right = mid;
				intervalTreeIndex = LEFT_SUBTREE(intervalTreeIndex);
			}
		}
		
		if (compare(vValues[intervalTree[intervalTreeIndex]], vValues[foundIndex]))
		{
			foundIndex = intervalTree[intervalTreeIndex];
		}
		
		return foundIndex;
	}

	Compare			compare;
	int				intervalSize;
	int				*intervalTree;
	T				*vValues;
};

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

	IntervalTree<int, greater<int> > intervalTree(intervalSize, 0);
	for (int i=0; i<intervalSize; ++i)
	{
		int x;
		fin >> x;
		intervalTree.Update(i,x);
	}
	
	for (int i=0; i<m; ++i)
	{
		int opt, a, b;
		fin >> opt >> a >> b;

		switch (opt)
		{
			case 0:
			{
				fout << intervalTree.QueryValue(a-1,b-1) << "\n";
			}; break;
			
			case 1:
			{
				intervalTree.Update(a-1,b);
			}; break;
		}
	}
	
	fin.close();
	fout.close();
	
	return 0;
}