Cod sursa(job #2232885)

Utilizator iondodon1998Dodon Ion iondodon1998 Data 21 august 2018 16:01:06
Problema Arbori indexati binar Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 4.14 kb
/**
 *  Tushar Roy --> https://www.youtube.com/watch?v=CWDQJGaN1gY&t=10s
 *  GeeksForGeeks --> https://www.youtube.com/watch?v=4SNzC4uNmTA&t=165s
 */

#include <fstream>
#define N_MAX 100000

int N, M;
FILE *fin, *fout;

void swap(int &a, int &b){
    int temp = a;
    a = b; b = temp;
}

class BinaryIndexTree{
private:
    int bit_prefix_sum[N_MAX+1];
    int bit_index_keeper[N_MAX+1];

    int getNextNode(int previous) {
        return previous + (previous & -previous);
    }

    int getParent(int child) {
        return child - (child & -child);
    }

    void qSortIndexes(int left, int right){
        int i = left, j = right;
        int middle = (left + right) / 2;

        while(i < j) {
            while (bit_prefix_sum[bit_index_keeper[i]] < bit_prefix_sum[bit_index_keeper[middle]])
                i++;
            while (bit_prefix_sum[bit_index_keeper[j]] > bit_prefix_sum[bit_index_keeper[middle]])
                j--;

            if (i <= j) {
                swap(bit_index_keeper[i],bit_index_keeper[j]);
                i++; j--;
            }

            //if equal, sort by index, which means cancelling the previous `swap()`
            if(bit_prefix_sum[bit_index_keeper[i]] == bit_prefix_sum[bit_index_keeper[j]]){
                if(bit_index_keeper[i] > bit_index_keeper[j])
                    swap(bit_index_keeper[i],bit_index_keeper[j]);
            }
        }

        if(j > left) qSortIndexes(left,j);
        if(i < right) qSortIndexes(i, right);
    }

    int bSearch(int sum_to_find, int left, int right){
        int middle = 0;

        while(left < right){
            middle = (left + right) / 2;
            if(sum_to_find <= bit_prefix_sum[bit_index_keeper[middle]]){
                right = middle;
            }
            else
                if(sum_to_find > bit_prefix_sum[bit_index_keeper[middle]]){
                    left = middle + 1;
                }
        }

        if(left == right && sum_to_find == bit_prefix_sum[bit_index_keeper[left]])
            return bit_index_keeper[left];
        else
            return -1;

        /*if(bit_prefix_sum[bit_index_keeper[middle]] == sum_to_find){
            return bit_index_keeper[middle];
        } else
            if(bit_prefix_sum[bit_index_keeper[middle]] >= sum_to_find && left < middle)
                bSearch(sum_to_find, left, middle);
            else
                if(bit_prefix_sum[bit_index_keeper[middle]] < sum_to_find && right > middle)
                    bSearch(sum_to_find, middle+1, right);
            else return -1;*/
    }

public:
    void update(int i, int val_to_add) {
        while(i <= N){
            bit_prefix_sum[i] += val_to_add;
            i = getNextNode(i);
        }
    }

    int getSumUpTo(int i) {
        int sum = 0;
        while(i > 0){
            sum = sum + bit_prefix_sum[i];
            i = getParent(i);
        }
        return sum;
    }

    void setIndex(int index){
        bit_index_keeper[index] = index;
    }

    //quick sort + binary search O(log^2(n))
    int getMinIndexOfSum(int sum_to_find){
        qSortIndexes(1,N);
        return bSearch(sum_to_find, 1, N);
    }

} BITree;

void constructBITree(){
    fscanf(fin, "%d%d", &N, &M);
    for(int i = 1, new_value; i <= N; i++){
        fscanf(fin, "%d", &new_value);
        BITree.update(i, new_value);
        BITree.setIndex(i);
    }
}

void solve(){
    int operation, a, b, sum;
    for(int i = 1; i <= M; i++){
        fscanf(fin, "%d", &operation);

        switch(operation){
            case 0:
                fscanf(fin, "%d%d", &a, &b);
                BITree.update(a, b);
                break;
            case 1:
                fscanf(fin, "%d%d", &a, &b);
                fprintf(fout, "%d\n", BITree.getSumUpTo(b) - BITree.getSumUpTo(a-1));
                break;
            case 2:
                fscanf(fin, "%d", &sum);
                fprintf(fout, "%d\n", BITree.getMinIndexOfSum(sum));
                break;
            default:
                fprintf(fout, "Invalid operation!\n");
        }
    }
}

int main(){
    fin = fopen("aib.in", "r");
    fout = fopen("aib.out", "w");
    constructBITree();
    solve();
    fclose(fin);
    fclose(fout);
    return 0;
}