Cod sursa(job #61395)

Utilizator yoyolichIoana Ardeleanu yoyolich Data 19 mai 2007 11:49:57
Problema Datorii Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.87 kb
#include <cstdio>
#define left(i) ((i)<<1)
#define right(i) (((i)<<1)|1)
#define mijloc(i, j) (((i)+(j))>>1)
#define maxn 1<<15
//VECTORUL S trebuie sa aiba un numar MAI MARE decat 2*n dar sa fie de forma 2^k (arborele trebuie sa fie complet)
// cu ajutorul arborilor de intervale se pot rezolva mai multe tipuri de probleme decat se poate rezolva cu arborii indexati binar
// de ce am folosit "define-urile" in loc sa folosesc functii? (ex: int left(int i)  { return (i<<1);})
// pt k in momentul compilarii, c-ul sterge unde gaseste "left(i)" si scrie i<<1 , pe scurt nu se apeleaza nici o functie
// e ca si cum am scrie direct
// mijloc(i, j) = (i+j)/2
// left(i) = 2*i
// right(i) = 2*i+1
// operatiile pe biti sunt de vreo 10 ori mai rapide decat inmultirile sau impartirile si de vreo 2 ori mai rapide decat adunarile si scaderile ;))
// 1<<15 = 2^15= (aproximativ)32000
int s[maxn], n, m;
//sgn = semn ( se aduna sau se scada)
//daca nu puneam sgn trebuia sa fi scris de 2 ori functia...odata pt initializare si odata pt operatii
void update(int n, int l, int r, int p, int v, int sgn)
{
  int m=mijloc(l,r);
  s[n]+=v*sgn;
  if(l==r) return;
  if(p<=m) update(left(n), l, m, p, v, sgn);
  else update(right(n), m+1, r, p, v, sgn);
}

int query(int n, int l, int r, int a, int b)
{
  int t=0;
  if(a<=l && r<=b)return s[n];
  int m=mijloc(l, r);
  if(a<=m) t+=query(left(n), l, m, a, b);
  if(b>m) t+=query(right(n), m+1, r, a, b);
  return t;
}

int main()
{
  int i;
  freopen("datorii.in", "r", stdin);
  freopen("datorii.out", "w", stdout);
  scanf("%d %d\n", &n, &m);
   for(i=1;i<=n;i++){ int p; scanf("%d ", &p); update(1, 1, n,i, p, 1);}
  


  for(i=1;i<=m;i++)
    {
      int p, q, t;
      scanf("%d %d %d\n", &p, &q, &t);
      if(p==0) update(1,  1, n, q, t, -1);
      else printf("%d\n", query(1, 1, n, q, t));
    }

  return 0;
}