Cod sursa(job #3183551)

Utilizator Panainte_TheodoraPanainte Theodora Panainte_Theodora Data 12 decembrie 2023 10:53:19
Problema Arbori indexati binar Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.75 kb
#include <bits/stdc++.h>
#define Nat unsigned int
using namespace std;

/**
Arbori indexati binar

Se da un vector a1, a2, ..., an
si se dau Q operatii de doua tipuri:
1 p x : a[p] += x
2 x y : cat este suma a[x]+...+a[y]?

    1 2 3 4 5 6 7 8
a = 1 2 3 4 5 6 7 8

Construim un vector aib[] de lungime n
in care
aib[i] = suma elementelor de pe
  intervalul a[i-2^k+1]...a[i],
  unde k=numarul de biti de 0
  de la finalul reprezentarii lui i
  in baza 2

indice  baza2   interval  suma
1       0001    [1,1]       1
2       0010    [1,2]       3
3       0011    [3,3]       3
4       0100    [1,4]       10
5       0101    [5,5]       5
6       0110    [5,6]       11
7       0111    [7,7]       7
8       1000    [1,8]       36

2 2 7 : a[2]+a[3]+...+a[7] =
        a[1]+a[2]+...+a[7] - a[1]
        [7,7]+[5,6]+[1,4] - [1,1]=
        aib[7] + aib[6]+aib[4]-aib[1]

In general interogarea
2 x y o transformam in
suma(a[1]+...+a[y])-suma(a[1]+...a[x-1])

a[p] += x;
a[3] += 10

aib[3] += 10
3+2^0 = 4 : aib[4] += 10
4+2^2 = 8 : aib[8] += 10
*/
ifstream fin("aib.in");
ofstream fout("aib.out");
unsigned int aib[100004], n, Q;

void UpdateOld(Nat p, Nat x)
{
    while (p <= n)
    {
        aib[p] += x;
        /// aflu cea mai mare putere a lui
        /// 2 divizibila cu p
        int k = 1; /// 2^0
        while (p % k == 0)
            k = k * 2;
        k /= 2;
        p = p + k;
    }
}

void Update(Nat p, Nat x)
{
    while (p <= n)
    {
        aib[p] += x;
        p += (p & (-p));
    }
}
/// ret. suma a[1]+a[2]+...a[p]
Nat Query(Nat p)
{
    Nat suma = 0;
    while (p > 0)
    {
        suma += aib[p];
        p -= (p & (-p));
    }
    return suma;
}

/// cauta cea mai din stanga pozitie p
/// in care sum(a[1..p]) = x
/// daca nu exista pozitia p, afisam -1
void CautBin(Nat x)
{
    Nat st, dr, mij, p, val;
    st = 1; dr = n;
    p = 0;
    while (st <= dr)
    {
        mij = (st + dr) / 2;
        val = Query(mij);
        if (val == x)
        {
            p = mij;
            dr = mij - 1;
        }
        else if (val < x) st = mij + 1;
        else dr = mij - 1;
    }
    if (p == 0) fout << "-1\n";
    else fout << p << "\n";
}

int main()
{
    Nat x, y, op, i;
    fin >> n >> Q;
    for (i = 1; i <= n; i++)
    {
        fin >> x;
        Update(i, x);
    }
    for (i = 1; i <= Q; i++)
    {
        fin >> op;
        if (op == 0)
        {
            fin >> x >> y;
            Update(x, y);
        }
        else if (op == 1)
        {
            fin >> x >> y;
            fout << Query(y) - Query(x-1)<<"\n";
        }
        else
        {
            fin >> x;
            CautBin(x);
        }
    }
    return 0;
}