Cod sursa(job #2984877)

Utilizator VDAVIDVladuca david VDAVID Data 25 februarie 2023 02:32:51
Problema Arbori indexati binar Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.65 kb
#include <bits/stdc++.h>

using namespace std;

const int NMAX = 1e5 + 1;
int v[NMAX], aib[NMAX];
int n, m;

/**
    Def : Adica primul bit 1 din scrierea in baza 2 a lui x.
    Ex. least_significant_bit(6) = ?
        6 -> in baza 2 = 00000110
                               ^
              x & (-x) = 00000010
    => least_significant_bit(6) = 00000010
**/

int least_significant_bit(int x) {
    return x & (-x);
}


/**
    Def. update(nod, val) = cresc cu val toate intervalele afectate
                            de cresterea lui v[nod] cu val

    Acest update este folosit si la construirea aib-ului!
**/

void update(int nod, int val) {
    while(nod <= n) {
        /// se cresc cu val intervalele care il contin pe nod
        aib[nod] += val;

        /// trecem la urmatorul interval care il contine pe nod
        nod += least_significant_bit(nod);
    }
}

/**
    Def. query(nod) = suma din intervalul [1, nod]

    Explicatie :
    - daca incepem de la aib[nod], deja ajungem la un
        interval [x, nod], care este chiar intervalul terminal

    - de aici, de fiecare data cand la parintele nodului ajungem,
        la un alt interval [y, x-1], s.a.m.d. pana cand ajungem la [1, z].

    - insumate, ele dau chiar intervalul [1, nod]

**/

int query(int nod) {
    int sum = 0;
    while(nod) {
        /// ne aflam pe un interval din interiorul lui [1, nod]
        sum += aib[nod];

        /// trecem la parintele lui nod
        nod -= least_significant_bit(nod);
    }
    return sum;
}


/// efectiv facem cautare binara clasica
int cb(int sum) {
    int st = 1, dr = n, ind = -1;
    while(st <= dr) {
        int mij = (st + dr) / 2;
        int s = query(mij); // suma din intervalul [0, s]
        if(s == sum)
            ind = mij;
        if(s < sum)
            st = mij + 1;
        else
            dr = mij - 1;
    }
    return ind;
}

int main() {
    ifstream cin("aib.in");
    ofstream cout("aib.out");
    cin >> n >> m;
    for(int i = 1; i <= n; i++) {
        int x;
        cin >> x;
        update(i, x);
    }

    for(int i = 1; i <= m; i++) {
        int c;
        cin >> c;
        if(c == 0) { // la v[poz] se adauga val
            int poz, val;
            cin >> poz >> val;
            update(poz, val);
        }
        else if(c == 1) { // suma din intervalul [a, b];
            int a, b;
            cin >> a >> b;
            cout << query(b) - query(a - 1) << '\n';
        }
        else { // x = ? a.i. query(x) == sum
            int sum;
            cin >> sum;
            cout << cb(sum) << '\n';
        }
    }
    return 0;
}