Cod sursa(job #3324473)

Utilizator adidavidDumitrascu Adrian David adidavid Data 22 noiembrie 2025 11:12:17
Problema Cautare binara Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.79 kb
/*lastequal() - cautam ultima aparitie exacta a lui x (cel mai mare index cu v[i] == x)
last(x) - cautam ultima pozitie v[i] <= x
fisrt(x) - cautam prima pozitie v[i] >= x

toate functiile au aceeasi idee:
mentinem un interval [st, dr] in care sigur se afla raspunsul (daca exista)
calculam un mid
verificam conditia:
daca elementul din mid este "bun", il retinem in ans si incercam sa gasim unul mai bun (mai la dreapta sau mai la stanga)
daca nu e bun, micsoram intervalul
*/
#include <bits/stdc++.h>
using namespace std;

ifstream in("cautbin.in");
ofstream out("cautbin.out");

int v[100001];
int n, m;

// 0 x: ultima pozitie pe care apare exact x
int lastEqual(int x) {
    int st = 1, dr = n;
    int ans = -1;              // -1 = nu am gasit (inca) un x
    
    while (st <= dr) {
        int mid = st + (dr - st) / 2;  // mijlocul intervalului [st, dr]
        
        if (v[mid] == x) {
            ans = mid;         // am gasit un x pe pozitia mid
            st = mid + 1;      // caut mai la dreapta, poate mai apare x
        } else if (v[mid] < x) {
            st = mid + 1;      // toate din stanga+mid sunt < x, merg la dreapta
        } else {
            dr = mid - 1;      // v[mid] > x, reduc intervalul la stanga
        }
    }
    return ans;                // ultima pozitie cu v[pos] == x sau -1
}

// 1 x: ultima pozitie pe care v[pos] <= x
int lastLE(int x) {
    int st = 1, dr = n;
    int ans = -1;
    
    while (st <= dr) {
        int mid = st + (dr - st) / 2;
        
        if (v[mid] <= x) {
            ans = mid;         // v[mid] e bun (<= x)
            st = mid + 1;      // incercam sa mergem mai la dreapta
        } else {
            dr = mid - 1;      // v[mid] > x, mergem in stanga
        }
    }
    return ans;
}

// 2 x: prima pozitie pe care v[pos] >= x
int firstGE(int x) {
    int st = 1, dr = n;
    int ans = -1;
    
    while (st <= dr) {
        int mid = st + (dr - st) / 2;
        
        if (v[mid] >= x) {
            ans = mid;         // v[mid] e bun (>= x)
            dr = mid - 1;      // incercam sa mergem mai la stanga
        } else {
            st = mid + 1;      // v[mid] < x, trebuie sa mergem in dreapta
        }
    }
    return ans;
}

int main() {
    in >> n;
    for (int i = 1; i <= n; i++)
        in >> v[i];            // sirul este deja ordonat crescator
    
    in >> m;
    while (m--) {
        int tip, x;
        in >> tip >> x;
        
        // switch pentru tip deoarece este un numar int, este doar 0 1 sau 2
        if (tip == 0) {
            out << lastEqual(x) << '\n';
        } else if (tip == 1) {
            out << lastLE(x) << '\n';
        } else { // tip == 2
            out << firstGE(x) << '\n';
        }
    }
    
    return 0;
}