Cod sursa(job #621989)

Utilizator claudiumihailClaudiu Mihail claudiumihail Data 17 octombrie 2011 04:30:55
Problema Arbori de intervale Scor 50
Compilator cpp Status done
Runda Arhiva educationala Marime 3.79 kb
#include <fstream>
#include <iostream>
#include <vector>
#include <stack>

#define maximum(a,b)	\
({						\
	typeof(a) _a = a;	\
	typeof(b) _b = b;	\
	_a>=_b?_a:_b;		\
})

using namespace std;

template<class T>
class SegmentTree
{
public:
	SegmentTree()
	{}
	
	SegmentTree(const unsigned int size) :
		tree(4*size+66,-1)
	{}
	
	void updateValue
	(
		const int nodeIndex,
		const int pos,
		const T& val,
		int left,
		int right
	)
	{
		/*if (left == right)
		{
			tree[nodeIndex] = val;
		}
		else
		{
			const int div = (left+right)/2;
			
			if (pos <= div)
				updateValue((nodeIndex<<1)+1, pos, val, left, div);
			else
				updateValue((nodeIndex+1)<<1, pos, val, div+1, right);
			
			tree[nodeIndex] = 
				maximum(tree[(nodeIndex<<1)+1], tree[(nodeIndex+1)<<1]);
		}*/
		int parent;
		int curNodeIndex = nodeIndex;
		stack<Context> st;
		
		st.push(Context(nodeIndex, left, right));

		while (!st.empty())
		{
			const Context ctx = st.top();
			
			if (ctx.left == ctx.right)
			{
				tree[ctx.nodeIndex] = val;
				curNodeIndex = ctx.nodeIndex;
				break;
			}
			else
			{
				const int div = (ctx.left+ctx.right)/2;
				//cout << div << endl;
				if (pos <= div)
				{
					st.push(Context((ctx.nodeIndex<<1)+1, ctx.left, div));
				}
				else
				{
					st.push(Context((ctx.nodeIndex+1)<<1, div+1, ctx.right));
				}
			}
		}

		parent = (curNodeIndex-1-!(curNodeIndex%2))>>1;
		while (parent>=0)
		{
			const int child1 = (parent<<1)+1;
			const int child2 = (parent+1)<<1;
			
			tree[parent] = maximum(tree[child1], tree[child2]);
			
			curNodeIndex = parent;
			parent = (curNodeIndex-1-!(curNodeIndex%2))>>1;
			
			//cout << "Parent is " << parent << endl;
		}
	}
	
	const T& queryInterval
	(
		const int nodeIndex,
		const int start,
		const int end,
		const int left,
		const int right
	) const
	{
		int maxi = -1;
		int indexOfMax = -1;
		stack<Context> st;
		
		st.push(Context(nodeIndex,left,right));
		
		while (!st.empty())
		{
			const Context ctx = st.top();
			st.pop();
			
			if (start <= ctx.left && ctx.right <= end)
			{
				if (maxi < tree[ctx.nodeIndex])
				{
					maxi = tree[ctx.nodeIndex];
					indexOfMax = ctx.nodeIndex;
				}
			}
			else
			{
				const int div = (ctx.left+ctx.right)/2;
				if (start <= div)
				{
					st.push(Context((ctx.nodeIndex<<1)+1, ctx.left, div));
				}
				if (div < end)
				{
					st.push(Context((ctx.nodeIndex+1)<<1, div+1, ctx.right));
				}
			}
		}
		
		return tree[indexOfMax];
	}
	
	void printTree() const
	{
		for (unsigned int i=0; i<tree.size(); ++i)
		{
			cout << tree[i] << " ";
		}
		cout << "\n";
	}

private:
	vector<T> tree;
	
	struct Context
	{
		Context()
		{}
		
		Context(const int index, const int l, const int r) :
			nodeIndex(index),
			left(l),
			right(r)
		{}

		int nodeIndex;
		int left;
		int right;
	};
};

int main()
{
	int n,m;
	fstream fin("arbint.in", fstream::in);
	fstream fout("arbint.out", fstream::out);
	
	fin >> n >> m;
	//cout << n << " " << m << endl;
	
	SegmentTree<int> segTree(n);
	
	for (int i=0; i<n; ++i)
	{
		int x;
		fin >> x;
		//cout << "Read " << x << " for position " << i << endl;
		segTree.updateValue(0,i,x,0,n-1);
		//segTree.printTree();
		
		//cout << endl;
	}
	
	for (int i=0; i<m; ++i)
	{
		int op, a, b;
		fin >> op >> a >> b;
		
		switch (op)
		{
			case 0:
			{
				//cout << op << " " << a-1 << " " << b-1 << "\n";
				fout << segTree.queryInterval(0, a-1, b-1, 0, n-1) << "\n";
			}; break;
			
			case 1:
			{
				//cout << op << " " << a-1 << " " << b << "\n";
				segTree.updateValue(0,a-1,b,0,n-1);
				//segTree.printTree();
			}; break;
		}
		//cout << "\n";
	}
	
	fin.close();
	fout.close();
	return 0;
}