Pagini recente » Cod sursa (job #931321) | Cod sursa (job #2623669) | Cod sursa (job #192397) | Cod sursa (job #3290427) | Cod sursa (job #2763233)
#include <iostream>
#include <fstream>
class SegmentTree{
public:
/// Creeaza un nou arbore de intervale pentru intervalul [x, y]
/// Parametrii:
/// x: Inceputul intervalului
/// y: Finalul intervalului
/// Complexitate: Theta(n*log(n))
/// Complexitate spatiu: Theta(n*log(n)), unde n = y - x + 1
SegmentTree(int x, int y):
x{x}, y{y}, val{INITIAL_VALUE}, valToPropagate{INITIAL_VALUE}, needToPropagate{false}, left{nullptr}, right{nullptr}
{
if (x != y)
{
int mid = (x + y) / 2;
left = new SegmentTree(x, mid);
right = new SegmentTree(mid + 1, y);
}
}
/// Actualizeaza valoarea de pe pozitiile din intervalul [p1, p2] cu valoarea data (value)
/// Parametrii:
/// p1: Inceputul intervalului de actualizare
/// p2: Finalul intervalului de actualizare
/// value: Valoarea cu care se actualizeaza
/// Complexitate: O(log(n))
void Update(int p1, int p2, int value)
{
Propagate();
if (p2 < x || p1 > y) // asta inseamna ca sunt intr-un interval care nu contine pozitia pe care o caut
return;
if (p1 <= x && y <= p2) // Am ajuns la un interval care e inclus in intervalul in care am de cautat
{
valToPropagate = value;
needToPropagate = true;
Propagate();
return;
}
// Trimit Update-ul spre stanga si spre dreapta
left->Update(p1, p2, value);
right->Update(p1, p2, value);
// Actualizez valoarea din nodul curent, care retine informatii pentru tot intervalul [x, y]
val = std::max(left->val,right->val); // pentru sume
}
/// Se gaseste suma/maximul/minimul pe intervalul [lo, hi]
/// Parametrii:
/// lo: Inceputul intervalului pentru query
/// hi: Finalul intervalului pentru query
/// Complexitate: O(log(n))
int Query(int lo, int hi) // Care este suma/minimul/maximul din intervalul [lo, hi]
{
Propagate();
if (y < lo || x > hi) // sunt in afara intervalului pentru query
return INITIAL_VALUE;
if (lo <= x && y <= hi) // intervalul curent este inclus de intervalul pe care il caut
return val;
int t1 = left->Query(lo, hi);
int t2 = right->Query(lo, hi);
return std::max(t1, t2);
}
private:
void Propagate()
{
if (!needToPropagate) // daca totul e actualizat
return;
if (left != nullptr)
{
left->valToPropagate = valToPropagate;
right->valToPropagate = valToPropagate;
}
val = valToPropagate;
valToPropagate = INITIAL_VALUE;
needToPropagate = false;
}
int x, y; // intervalul pe care il retine nodul curent
int val; // valoarea de la acest nod - poate fi o suma, un minim, un maxim etc.
int valToPropagate; // aceasta valoare trebuie actualizata pe tot intervalul [x, y], pe masura ce inaintam in arbore de la acest nod in jos
bool needToPropagate; // true daca trebuie actualizat intervalul [x, y] cu ceea ce se afla in valToPropagate
SegmentTree *left, *right; // fiul stang si fiul drept al arborelui
const static int INITIAL_VALUE = 0; // Ar trebui sa fie valoarea initiala din sir. Pentru sume e 0
};
int main()
{
std::ifstream fin("arbint.in");
std::ofstream fout("arbint.out");
int N, Q;
int type, a, b;
fin >> N >> Q;
SegmentTree st(1, N);
for (int i = 1; i <= N; ++i)
{
fin >> a;
st.Update(i, i, a);
}
while (Q--)
{
fin >> type >> a >> b;
if (type == 0)
{
fout << st.Query(a, b) << '\n';
}
else
{
st.Update(a, a, b);
}
}
fin.close();
fout.close();
}