Cod sursa(job #1195173)

Utilizator juniorOvidiu Rosca junior Data 6 iunie 2014 16:51:55
Problema Arbori indexati binar Scor 80
Compilator cpp Status done
Runda Arhiva educationala Marime 1.83 kb
#include <stdio.h>
#include <fstream>

using namespace std;

#define in "aib.in"
#define out "aib.out"
#define dim 100001

inline int Minim(int a, int b) {
  if ( a < b ) return a;
  return b;
}

int N, O, T;
int Arb[dim];
int C, S;

void Update(int, int);
int Query(int);
int Search(int);

int main() {
  int cod, a, b;

  freopen(in, "r", stdin);
  freopen(out, "w", stdout);
  scanf("%d%d", &N, &O);
  for ( int i = 1; i <= N; i++ ) {
    scanf("%d", &T);
    Update(i, T); // Adunam T la 0.
  }
  for ( ; O; O-- ) {   // operatiile
    scanf("%d", &cod); // codul operatiei
    if ( cod < 2 )  {
      scanf("%d %d", &a, &b);
      if (cod == 0)
        Update(a, b);
      else
        printf("%d\n", Query(b) - Query(a - 1));
    }
    else {
      scanf("%d", &a);
      printf("%d\n", Search(a));
    }
  }
}

int Search(int Sum) {
  int pos = N + 1, B;
  int limst = 0, limdr = N + 1;

  B = N;
  S = Query(B);
  if ( S == Sum ) pos = N;
  while ( B ) {
    B = (limst + limdr) >> 1;
    S = Query(B);
    if ( S > Sum ) {
      if ( limdr > B )
        limdr = B;
      B -= 1;
    }
    else
      if ( S == Sum )
        pos = Minim(pos, B), limdr = B, B -= 1;
      else {
        if ( limst < B )
          limst = B;
        B += 1;
      }
    if ( B <= limst )
      break;
    if ( B >= limdr )
      break;
  }
  if ( pos == N + 1 )
    return -1;
  return pos;
}

void Update(int poz, int val) {
  C = 0;
  while ( poz <= N ) {
    Arb[poz] += val;
    while ( !(poz & (1 << C)) ) // Numaram cate cifre de 0 sunt la sfarsitul lui poz.
      C++;
    poz += (1 << C);
  }
}

int Query(int poz) {
  C = 0, S = 0;
  while ( poz > 0 )
  {
    S += Arb[poz];
    while ( !(poz & (1 << C)) )
      C++;
    poz -= (1 << C);
    //C += 1;
  }
  return S;
}