Cod sursa(job #1119123)

Utilizator fhandreiAndrei Hareza fhandrei Data 24 februarie 2014 15:27:09
Problema Arbori de intervale Scor 50
Compilator cpp Status done
Runda Arhiva educationala Marime 2.79 kb
// Include
#include <fstream>
using namespace std;

// Definitii
#define leftSon node*2
#define rightSon node*2+1

// Constante
const int sz = (int)1e5+1;

// Functii
// Modifica elementul de pe pozitia pos a vectorului in valoarea val.
// In arbore, elementul va reprezenta intervalul [pos, pos] si se va gasi pe pozitia node
void update(int node, int left, int right, int pos, int val);
// Returneaza valoarea maxima de pe intervalul leftRange, rightRange.
// Variabilele node, left si right simbolizeaza acelasi lucru ca in functia update
int query(int node, int left, int right, int leftRange, int rightRange);

// Variabile
ifstream in("arbint.in");
ofstream out("arbint.out");

int num;
int questions, type;

int tree[4*sz];

// Main
int main()
{
	in >> num >> questions;
	int val;
	for(int i=1 ; i<=num ; ++i)
	{
		in >> val;
		update(1, 1, num, i, val);
	}
	
	while(questions--)
	{
		in >> type;
		int pos, val, leftRange, rightRange;
		if(type)
		{
			in >> pos >> val;
			update(1, 1, num, pos, val);
		}
		else
		{
			in >> leftRange >> rightRange;
			out << query(1, 1, num, leftRange, rightRange) << '\n';
		}
	}
	
	in.close();
	out.close();
	return 0;
}

void update(int node, int left, int right, int pos, int val)
{
	// Daca am ajuns la un interval unitar, updatez arborele
	if(left == right)
	{
		tree[node] = val;
		return;
	}
	
	// In caz contrar, ma uit in ce directie trebuie sa merg, in functie de pozitia pe care trebuie pus elementul
	int mid = (left + right) / 2;
	if(pos <= mid)
		update(leftSon, left, mid, pos, val);
	else
		update(rightSon, mid+1, right, pos, val);
	
	// Valoarea de pe nodul curent va fi maximul de pe intervalul [left, right] ce-l reprezinta, deci maximul fiilor
	tree[node] = max(tree[leftSon], tree[rightSon]);
}

int query(int node, int left, int right, int leftRange, int rightRange)
{
	// Daca intervalul curent [left, right] e continut in intervalul mare [leftRange, rightRange]
	// Returnez valoarea maxima a intervalului
	if(leftRange <= left && right <= rightRange)
		return tree[node];
	
	// In caz contrar, ma uit in ce directie trebuie sa merg, in functie de pozitia intetrvalului cautat.
	// E posibil ca raspunsul sa fie o reuniune de intervale, deci va trebui sa le verific pe ambele
	int mid = (left + right) / 2;
	
	int max1=0, max2=0;
	
	// Daca capatul din stanga al intervalului cautat este in stanga mijlocului, trebuie sa caut in intervalul [left, mid]
	if(leftRange <= mid)
		max1 = query(leftSon, left, mid, leftRange, rightRange);
	
	// Daca capatul din dreapta al intervalului cautat este in dreapta mijlocului, trebuie sa caut in intervalul (mid, right]
	if(mid < rightRange)
		max2 = query(rightSon, mid+1, right, leftRange, rightRange);
	
	return max(max1, max2);
}