Cod sursa(job #3345262)

Utilizator MH_06_001CLIMNR1 MH_06_001 Data 8 martie 2026 19:33:39
Problema Arbori de intervale Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.78 kb
#include <fstream>
#include <cmath>
#include <algorithm>

using namespace std;

// Deschidem fișierele folosind fstream (fin și fout)
ifstream fin("arbint.in");
ofstream fout("arbint.out");

int valoare[100005];      // Vectorul cu numerele noastre
int maxim_cutie[400];     // "Eticheta" cu maximul pentru fiecare cutie
int N,M;
int cat_de_mare_e_cutia;  // Aceasta este valoarea sqrt(N)

int main()
{
    // 1. Citim N și M
    fin>>N>>M;

    // 2. Calculăm cât de mare să fie o "cutie"
    cat_de_mare_e_cutia=sqrt(N);

    // 3. Citim numerele și, în același timp, pregătim "eticheta" fiecărei cutii
    for(int i=1;i<=N;i++)
    {
        fin>>valoare[i];

        // Aflăm în ce cutie trebuie să punem numărul i
        int nr_cutie=(i-1)/cat_de_mare_e_cutia+1;

        // Dacă e primul element din cutie, el e maximul momentan
        // Dacă nu, verificăm dacă e mai mare decât ce aveam deja în cutie
        if(i%cat_de_mare_e_cutia== 1 || i==1)
        {
            maxim_cutie[nr_cutie]=valoare[i];
        }
        else
        {
            if(valoare[i]>maxim_cutie[nr_cutie])
            {
                maxim_cutie[nr_cutie]=valoare[i];
            }
        }
    }

    // 4. Procesăm cele M operații
    for(int k=1;k<=M;k++)
    {
        int tip,X,Y;
        fin>>tip>>X>>Y;

        if(tip==1)
        {
            // --- UPDATE: Schimbăm valoarea de la poziția X cu numărul Y ---
            valoare[X]=Y;
            int nr_cutie=(X - 1)/cat_de_mare_e_cutia+1;

            // Când schimbăm un număr, trebuie să recalculăm maximul din cutia lui
            int inceput=(nr_cutie - 1)*cat_de_mare_e_cutia+1;
            int sfarsit=nr_cutie*cat_de_mare_e_cutia;
            if(sfarsit>N)
                sfarsit=N;

            maxim_cutie[nr_cutie]=-1; // Resetăm eticheta
            for(int j=inceput;j<=sfarsit;j++)
            {
                if(valoare[j]>maxim_cutie[nr_cutie])
                {
                    maxim_cutie[nr_cutie]=valoare[j];
                }
            }
        }
        else
        {
            // --- QUERY: Căutăm maximul între poziția X și poziția Y ---
            int maxim_final=-1;
            int cutia_start=(X - 1)/cat_de_mare_e_cutia+1;
            int cutia_final=(Y - 1)/cat_de_mare_e_cutia+1;

            if(cutia_start==cutia_final)
            {
                // Dacă X și Y sunt în aceeași cutie, căutăm normal între ele
                for(int j=X;j<=Y;j++)
                {
                    if(valoare[j]>maxim_final)
                        maxim_final=valoare[j];
                }
            }
            else
            {
                // Avem 3 părți de verificat:

                // Partea 1: De la X până la finalul cutiei în care se află X
                int sfarsit_cutie_X=cutia_start*cat_de_mare_e_cutia;
                for(int j=X;j<=sfarsit_cutie_X;j++)
                {
                    if(valoare[j]>maxim_final)
                        maxim_final=valoare[j];
                }

                // Partea 2: Cutiile "pline" de la mijloc (aici e viteza!)
                for(int c=cutia_start+1;c<cutia_final;c++)
                {
                    if(maxim_cutie[c]>maxim_final)
                        maxim_final=maxim_cutie[c];
                }

                // Partea 3: De la începutul cutiei lui Y până la poziția Y
                int inceput_cutie_Y=(cutia_final - 1)*cat_de_mare_e_cutia+1;
                for(int j=inceput_cutie_Y;j<=Y;j++)
                {
                    if(valoare[j]>maxim_final)
                        maxim_final=valoare[j];
                }
            }
            fout<<maxim_final<<"\n";
        }
    }
    return 0;
}