Cod sursa(job #2753716)

Utilizator Rares5000Baciu Rares Rares5000 Data 24 mai 2021 09:26:24
Problema Arbori indexati binar Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.17 kb
#include <bits/stdc++.h>
using namespace std;

/**
Arbori indexati binar

Se da un vector a=a1, a2, ..., an
si m operatii de forma:
0. (0 p x) : aduna valoarea x la a[p]
1. (1 i j) : care este suma a[i]+a[i+1]+...+a[j]?
2. (2 s) : care este cea mai din stanga
   poz. p cu a[1]+...+a[p]=s?
Trebuie sa raspundem la operatiile de tip 1
 si 2.

a = 1,2,3,4,0,0,0,8
m=5
1 3 3
1 4 5
2 3 8
1 5 1
2 4 7

a = 1,2,6,4,5,6,7,8
a = 1,2,6,9,5,6,7,8
41
a = 1,2,6,9,6,6,7,8
28

construim vectorul a astfel incat
aib[i] = suma pe un interval de lungime putere a lui 2
      Mai precis, a[i]=suma a[i+1-2^k]..a[i],
      unde k este numarul de biti terminali de 0
      din reprezentarea lui i in baza 2

a = 1,2,3,4,5,6,7,8
aib = 1,3,3,10,5,11,7,36

i  i(baza2)   intervalul    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

n = 100
suma a[43] + ... + a[88] =
a[1]+...+a[88] - (a[1]+...+a[42])

a[1]+...+a[88] = aib[88]+aib[80]+aib[64]
a[1]+...+a[42] = aib[42]+aib[40]+aib[32]

a[18]++
aib[18]++
aib[20]++
aib[24]++
aib[32]++
aib[64]++
*/
class AIB
{
private:
    int aib[100002];
    int n;
public:
    AIB(int dim)
    {
        n = dim;
        for (int i = 1; i <= n; i++)
            aib[i] = 0;
    }
    void Update(int p, int x)
    {
        while (p <= n)
        {
            aib[p] += x;
            /**
            /// calc. k
            int doilak = 1;
            while (p % doilak == 0)
                doilak *=2;
            doilak /= 2;
            p -= doilak;
            */
            p += (p & (-p));
        }
    }

    /// ret. suma elem. de la 1 la p
    int Query(int p)
    {
        int suma = 0;
        while (p > 0)
        {
            suma += aib[p];
            p -= (p & (-p));
        }
        return suma;
    }

    /// ret. cea mai din stanga pozitie p
    /// cu a[1]+...+a[p]=s,
    /// sau -1 daca nu exista o astfel de
    ///   pozitie
    int CautBin(int s)
    {
        int st, dr, p, mij, x;
        st = 1; dr = n; p = -1;
        while (st <= dr)
        {
            mij = (st + dr) / 2;
            x = Query(mij);
            if (x >= s)
            {
                if (x == s) p = mij;
                dr = mij - 1;
            }
            else st = mij + 1;
        }
        return p;
    }
};

int main()
{
    int i, n, m, op, x, y;
    ifstream fin("aib.in");
    ofstream fout("aib.out");
    fin >> n >> m;
    AIB w(n);
    for (i = 1; i <= n; i++)
    {
        fin >> x;
        w.Update(i, x);
    }
    for (i = 1; i <= m; i++)
    {
        fin >> op;
        if (op == 0)
        {
            fin >> x >> y;
            w.Update(x, y);
        }
        else if (op == 1)
        {
            fin >> x >> y;
            fout << w.Query(y) - w.Query(x-1)<<"\n";
        }
        else /// op == 2
        {
            fin >> y;
            fout << w.CautBin(y) << "\n";
        }
    }
    fout.close();
    return 0;
}