Pagini recente » Cod sursa (job #3195578) | Cod sursa (job #3177123) | Cod sursa (job #2595910) | Cod sursa (job #910509) | Cod sursa (job #1419108)
/*
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 ;
}