Cod sursa(job #3157114)

Utilizator BadHero112Ursu Vasile BadHero112 Data 14 octombrie 2023 13:33:42
Problema Arbori de intervale Scor 0
Compilator c-64 Status done
Runda Arhiva educationala Marime 2.95 kb
#include <stdio.h>
#include <stdlib.h>

//functie pentru a calcula maximul dintre doua numere intregi
int max (int a, int b) {
	if(a < b) return b;
	return a;
}

//functia pentru a construi arborele de intervale initial (indexarea se face de la 0)
void build (int *tree, int *array, int left, int right, int index) {
	int mid = (left + right) / 2;
	if(left == right) {
		// setam valoarea frunzelor de la nivelul inferior la valoarea corespunzatoare din array
		tree[index] = array[left];
	}
	else {
		//daca exista un nivel inferior nodului curent, setam recursiv valoarea nodurilor inferioare, apoi ne intoarcem in acesta si ii setam valoarea drept maximul dintre fii sai;
		build (tree, array, left, mid, index * 2 + 1);
		build (tree, array, mid+1, right, index * 2 + 2);
		
		tree[index] = max(tree[index * 2 + 1], tree[index * 2 + 2]);
	}
}

//functie de retragere a valorii maxime din array pe intervalul [left,right]
int query (int *tree, int left, int right, int node_left, int node_right, int index) {
	//daca intervalul curent se include complet in query, returnam valoarea nodului curent
	if(index==-2)return 0;
	if(node_left >= left && node_right <= right) {
		return tree[index];
	}
	//verificam daca nodul curent nu e complet in afara query-ului, caz in care il aruncam;
	else if(node_left > right || node_right < left) {
		return 0;
	}
	//de altfel, apelam query pe fii nodului curent, pentru ca nu putem determina inca nimic, si returnam maximul dintre raspunsuri;
	else {
		int mid = (node_left + node_right) / 2;
		return max (query (tree, left, right, node_left, mid, index * 2 + 1), query (tree, left, right, mid + 1, node_right, index * 2 + 2));
	}
}

//functie ce face update pe nodul target, schimbandu-i valoarea in new_value
void update (int *tree, int target, int new_value, int left, int right, int index) {
	int mid = (left + right) / 2;
	//daca am ajuns in nodul target, modificam valoarea sa si finalizam recursia;
	if(left == right) {
		tree[index] = new_value;
		return;
	}
	//alegem partea stanga sau drepta, in dependenta de unde se afla nodul target in arbore, si updatam fiul respectiv;
	if(target <= mid) {
		update (tree, target, new_value, left, mid, index * 2 + 1);
	}
	else {
		update (tree, target, new_value, mid + 1, right, index * 2 + 2);
	}
	tree[index] = max (tree[index * 2 + 1], tree[index * 2 + 2]);
}

int main() {
	//citim numarul de elemente, numarul de operatii si elementele;
	freopen("arbint.in","r",stdin);
	freopen("arbint.out","w",stdout);	
	int n, *array, q;
	scanf ("%d%d", &n, &q);
	array = (int*)malloc (n * sizeof (int));
	for (int i = 0; i < n; i++) {
		scanf ("%d", &array[i]);
	}
	//declaram si construim arborele de intervale
	int *tree;
	tree = (int*)malloc (4 * n * sizeof (int));
	build (tree, array, 0, n, 0);
	
	//rezolvam q queries
	while (q--) {
		int choice, a, b;
		scanf ("%d%d%d", &choice, &a, &b);
		a--;
		b--; 
		if (!choice) {
			printf ("%d\n", query (tree, a, b, 0, n, 0));
		}
		else {
			update (tree, a, b, 0, n, 0);
		}
	}
}