Cod sursa(job #1419108)

Utilizator stoianmihailStoian Mihail stoianmihail Data 14 aprilie 2015 18:41:32
Problema Datorii Scor 100
Compilator c Status done
Runda Arhiva de probleme Marime 4.96 kb
/*
  Algoritm problema "Datorii"

  Tinem intr-un AIB banii

  Pentru intrebari de tipul : 0 - facem update pozitia T din AIB
                            : 1 - facem diferenta dintre suma 1 -> Q
                                                              1 -> P - 1

  Complexitate :

  pentru citire + update : O( n * log n )
  pentru intrebari : O( log n )

  PerTotal : O( n * log n ) + Citire parsata + Iesire parsata

  Multumim Doamne !
*/
/// Bibliotecile care ne trebuiesc
#include <stdio.h> ///  pentru fread() + fwrite()
#include <ctype.h> /// pentru isdigit()
#include <math.h> /// pentru log2()
/// Constantele care ne trebuiesc
#define Nadejde  16384 /// marimea AIB -ului
#define Dragoste 4096 /// marimea bufferului
#define DIGITS   10 /// cate cifre are un int

/// variabilele de care avem nevoie
int  n ; /// numarul de clienti
int  i ; /// un index
int  lg ; /// log2(n)
int  LOG ; /// 2^( lg + 1 )
int  sum ; /// folosit la gasirea sumei
int  num ; /// citim vectorul
int  pay ; /// cat si-a platit din datorie
int  from ; /// intrebare 0
int  till ; /// intrebare 0
int  type ; /// ce tip de intrebare
int  where ; /// unde scadem datoria
int  Query ; /// cate intrebari
int  Shop[ Nadejde + 1 ] ; /// AIB -ul nostru
char c ; /// un caracter
char digits[ DIGITS ] ; /// vectorul cu cifrele numarului
char Buff[ Dragoste ] ; /// bufferul de iesire
char buff[ Dragoste ] ; /// bufferul oferit de sistem
short parse ; /// pozitia in Buff[]
short pos = Dragoste ; /// pozitia in buff[]
/// un fel de fgetc()
char getChar( FILE *fin )
{
     /// daca am golit buff[]
     if( pos == Dragoste )
       {
         fread( buff , 1 , Dragoste , fin ) ;
         pos = 0 ;
       }
     return buff[ pos ++ ];
}
/// un fel de fscanf() dar mai rapid :)
inline void fLaser( FILE *fin , int *result )
{
       *result = 0 ;
       /// pana ce gasim o cifra
       do{
          c = getChar( fin ) ;
       }while( !isdigit( c ) ) ;
       /// cand am gasit o cifra cream numarul
       do{
          *result = ( *result << 3 ) + ( *result << 1 ) + c - '0' ;
          c = getChar( fin ) ;
       }while( isdigit( c ) ) ;
}
/// un fel de fputc()
inline void putChar( FILE *fout , char ch )
{
       Buff[ parse ++ ] = ch ;
       /// daca s-a umplut Buff[]
       if( parse == Dragoste )
         {
           fwrite( Buff , 1 , Dragoste , fout ) ;
           parse = 0 ;
         }
}
/// un fel fprintf() dar mai rapid :)
inline void fPut( FILE *fout , int number )
{
       int div ;
       int dig = 0 ;

       do{
          /// facem catul impartirii la 10
          div = number / 10 ;
          /// punem cifra in vector
          digits[ dig ++ ] = number - ( div << 3 ) - ( div << 1 ) + '0' ;
          /// number /= 10
          number = div ;
       }while( number ) ;

       do{
          /// punem cifrele in Buff[]
          putChar( fout , digits[ -- dig ] ) ;
       }while( dig ) ;
}
/// golim Buff[]
void FlushBuff( FILE *fout )
{
     fwrite( Buff , 1 , parse , fout ) ;
}
/// luam suma din AIB pe pozitia x
int getSum( int x )
{
    sum = 0 ;

    while( x )
         {
           sum += Shop[ x ] ;
           x &= x - 1 ; /// scapam de ultimul bit
         }
    return sum ;
}
/// facem update la AIB pentru pozitia x
void Add( int val , int x )
{
     do{
        Shop[ x ] += val ;
        x += x & -x ; /// gasim urmatorul numar par din descompunerea lui x
     }while( x <= LOG ) ;
}
/// int main()
int main( )
{
    /// deschidere fisiere *C*
    FILE *fin = fopen( "datorii.in" , "r" ) ;
    FILE *fout = fopen( "datorii.out" , "w" ) ;
    /// citim parsat datele de intrare
    fLaser( fin , &n ) ;
    fLaser( fin , &Query ) ;
    /// calculam logaritmii
    lg = log2( n ) ;
    LOG = 1 << ( lg + 1 ) ;
    /// citim vectorul + facem update la AIB
    for( i = 1 ; i <= n ; i ++ )
       {
         fLaser( fin , &num ) ;
         /// facem update
         Add( num , i ) ;
       }
    /// pentru toate intrebarile
    while( Query )
         {
           fLaser( fin , &type ) ;
           /// tipul 0
           if( !type )
             {
               fLaser( fin , &where ) ;
               fLaser( fin , &pay ) ;
               /// scapam de datorie
               Add( -pay , where ) ;
             }
           /// tipul 1
           else
             {
               fLaser( fin , &from ) ;
               fLaser( fin , &till ) ;
               /// facem diferenta dintre : 1 -> till si 1 -> from - 1
               fPut( fout , getSum( till ) - getSum( from - 1 ) ) ;
               /// mereu linie noua
               putChar( fout , '\n' ) ;
             }
           /// decrementam Query
           Query -- ;
         }
    /// golim bufferul
    FlushBuff( fout ) ;
    /// inchidem fisierele
    fclose( fin ) ;
    fclose( fout ) ;
    /// Multumim Doamne !
    printf( "Hristos a inviat!" ) ;
    /// dai return 0
    return 0 ;
}