Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Contenidos
Introduccion
set de C++
Mnimo en intervalos (RMQ)
caso estatico: sparse tables
caso dinamico: segment tree
Suma en intervalos
caso estatico: sumas parciales uni- y bi-dimensionales
caso dinamico: binary indexed tree
Estructuras de datos
Introduccion
Qu
e es una estructura de datos?
Una forma de almacenar datos y operar con ellos de modo de
poder calcular eficientemente diversas magnitudes.
Puede pensarse como una caja negra donde estan los datos
(posiblemente sujetos a modificaciones), que nos respondera
cierto tipo de preguntas de modo eficiente.
C
omo se usa una estructura de datos en una competencia
de programaci
on?
Las etapas o pasos intermedios del algoritmo muchas veces pueden
verse como subproblemas menores, que debemos resolver para
hallar la respuesta final. Si bien los problemas completos rara vez
se repiten, los subproblemas muchas veces son clasicos, y
conocemos para ellos una estructura de datos adecuada.
Training Camp Argentina 2013
Estructuras de datos
set de C++
El set de C++ representa un conjunto de elementos, que
podemos pensar como ordenados de menor a mayor. Nos
permite realizar distintas operaciones en O(log N):
insertar y borrar elementos (insert y erase, resp.);
fijarnos si un elemento esta presente (find);
encontrar el primer elemento mayor o mayor o igual que
otro (upper bound y lower bound, respectivamente).
Algunas observaciones:
en un conjunto no puede haber repeticiones;
no controlamos el funcionamiento interno de la estructura,
solo la funcion de comparaci
on;
no podemos modificar elementos (pero s eliminar una version
vieja de un elemento y reemplazarla por una nueva).
Training Camp Argentina 2013
Estructuras de datos
#i n c l u d e <i o s t r e a m >
#i n c l u d e <s e t >
u s i n g namespace s t d ;
i n t main ( ) {
s e t <i n t > c ;
for ( int
c o u t << c . s i z e ( ) << e n d l ;
f o r ( s e t <i n t > : : i t e r a t o r i t =c . b e g i n ( ) ;
c o u t << i t << ;
i t != c . end ( ) ;
i t ++)
Estructuras de datos
s t r u c t pt {
int x , y ;
p t ( i n t xx =0 , i n t yy =0) {
x=xx ; y=yy ;
};
};
b o o l o p e r a t o r <( c o n s t p t &p1 , c o n s t p t &p2 ) {
d o u b l e a1=a t a n 2 ( p1 . y , p1 . x ) , a2=a t a n 2 ( p2 . y , p2 . x ) ;
i f ( a1 != a2 ) r e t u r n a1 < a2 ;
e l s e r e t u r n p1 . x p1 . x+p1 . y p1 . y < p2 . x p2 . x+p2 . y p2 . y ;
}
[...]
s e t <pt> p ;
p . i n s e r t ( pt (1 ,1) ) ; p . i n s e r t ( pt (2 ,2) ) ;
p . i n s e r t ( pt (2 ,1) ) ; p . i n s e r t ( pt (3 ,5) ) ;
Estructuras de datos
Aplicacion: Dijkstra
1 s e t < p a i r <i n t , i n t > > s ;
2
3 v o i d d i j k s t r a ( i n t s t a r t , i n t d e s t , i n t N) {
4
f o r ( i n t i =0; i <N ; i ++) n [ i ] . d = INF ;
5
n [ s t a r t ] . d = 0; s . i n s e r t ( make pair (0 , s t a r t ) ) ;
6
w h i l e ( ! s . empty ( ) ) {
7
i n t c u r = s . b e g i n ( )>s e c o n d ;
8
i f ( c u r == d e s t ) b r e a k ;
9
f o r ( i n t i =0; i <( i n t ) n [ c u r ] . c . s i z e ( ) ; i ++) {
10
i n t next = n [ cur ] . c [ i ] . f i r s t ;
11
i f ( n [ n e x t ] . d==INF | | n [ n e x t ] . d>n [ c u r ] . d+n [ c u r ] . c [ i ] . s e c o n d ) {
12
i f ( n [ n e x t ] . d != INF )
13
s . erase ( make pair (n [ next ] . d , next ) ) ;
14
n [ next ] . d = n [ cur ] . d + n [ cur ] . c [ i ] . second ;
15
s . i n s e r t ( make pair (n [ next ] . d , next ) ) ;
16
}
17
}
18
s . erase ( make pair (n [ cur ] . d , cur ) ) ;
19
}
20 }
Estructuras de datos
Problemas
Estructuras de datos
Estructuras de datos
para
k = 0, 1, . . .
Estructuras de datos
void
s t i n i t ( i n t m, i n t N, i n t s t ) {
f o r ( i n t i =0; i <N ; i ++) s t [ 0 ] [ i ] = m[ i ] ;
f o r ( i n t k =1; (1<<k )<=N ; k++) {
f o r ( i n t i =0; i +(1<<k )<=N ; i ++) {
i f ( s t [ k 1 ] [ i ] < s t [ k 1 ] [ i +(1<<(k 1) ) ] )
s t [ k ] [ i ] = s t [ k 1][ i ] ;
e l s e s t [ k ] [ i ] = s t [ k 1 ] [ i +(1<<(k 1) ) ] ;
}
}
}
i n t s t q u e r y ( i n t s t , i n t s , i n t e ) {
i n t k = 31
b u i l t i n c l z ( es ) ;
i f ( s t [ k ] [ s ] < s t [ k ] [ e(1<<k ) ] ) r e t u r n s t [ k ] [ s ] ;
e l s e r e t u r n s t [ k ] [ e(1<<k ) ] ;
}
RMQ estatico con sparse tables - O(N log N) init. y O(1) query
Training Camp Argentina 2013
Estructuras de datos
Estructuras de datos
10
11
100
1000
101
1001
1010
110
1011
1100
111
1101
1110
Estructuras de datos
1111
Estructuras de datos
#d e f i n e LEFT ( n ) ( 2 ( n ) )
#d e f i n e RIGHT ( n ) ( 2 ( n )+1 )
#d e f i n e NEUT 2147483647
i n t oper ( i n t a , i n t b) {
r e t u r n min ( a , b ) ;
}
v o i d r m q i n i t ( i n t n , i n t s , i n t e , i n t rmq , i n t m) {
i f ( s+1 == e ) rmq [ n ] = m[ s ] ;
else {
r m q i n i t ( LEFT ( n ) , s , ( s+e ) / 2 , rmq , m) ;
r m q i n i t ( RIGHT ( n ) , ( s+e ) / 2 , e , rmq , m) ;
rmq [ n ] = o p e r ( rmq [ LEFT ( n ) ] , rmq [ RIGHT ( n ) ] ) ;
}
}
Estructuras de datos
Estructuras de datos
Estructuras de datos
Suma en intervalos
Dado un arreglo de N n
umeros m0 , . . . , mN1 , queremos responder
preguntas de la forma
Cu
al es el valor de S [ i, j) = mi + + mj1 ?
El algoritmo ingenuo recorre todos los elementos en [i, j), y
requiere O(N) en el peor caso;
Si no se van a modificar los valores del arreglo, podemos
preprocesar en O(N) y responder preguntas en O(1);
Si los elementos del arreglo pueden cambiar, podemos
inicializar en O(N log N) y responder preguntas o modificar
valores en O(log N)
Estructuras de datos
v o i d i n i t ( i n t m, i n t sm , i n t N) {
sm [ 0 ] = 0 ;
f o r ( i n t i =1; i <=N ; i ++) sm [ i ] = sm [ i 1]+m[ i 1 ] ;
}
i n t q u e r y ( i n t sm , i n t a , i n t b ) {
r e t u r n sm [ b]sm [ a ] ;
}
Estructuras de datos
b1 d1
X
X
mij
i=a j=c
Estructuras de datos
Estructuras de datos
i n t g e t c f ( i n t idx , i n t b i t ) {
int cf = bit [ 0 ] ;
wh ile ( i d x > 0) {
c f += b i t [ i d x ] ;
i d x &= i d x 1;
}
return cf ;
}
void upd f ( i n t idx , i n t f , i n t b i t ) {
i f ( i d x == 0 ) b i t [ i d x ] += f ;
e l s e w h i l e ( i d x < MAXN) {
b i t [ i d x ] += f ;
i d x += i d x &( i d x ) ;
}
}
Estructuras de datos
v = mi
(viejo)
mi
Estructuras de datos
k
i+2
O1
h
mj O i, i + 2k
j=i
Estructuras de datos
v o i d i n i t ( i n t m, i n t sm , i n t N)
f o r ( i n t i =0; i <N ; i ++) sm [ 0 ] [
f o r ( i n t k =1; (1<<k )<=N ; k++)
f o r ( i n t i =0; i +(1<<k )<=N ;
sm [ k ] [ i ]= o p e r ( sm [ k 1 ] [
}
{
i ] = m[ i ] ;
i ++)
i ] , sm [ k 1 ] [ i +(1<<(k 1) ) ] ) ;
i n t q u e r y ( i n t sm , i n t a , i n t b ) {
i n t RES = 0 , l = ba ;
f o r ( i n t i =0; (1<< i )<=l ; i ++) i f ( l &(1<< i ) ) {
RES = o p e r ( RES , sm [ i ] [ a ] ) ;
a += (1<< i ) ;
}
r e t u r n RES ;
}
Estructuras de datos
Para mayor
comodidad, definimos ai = i N y
bi = (i + 1) N; luego el i-esimo segmento corresponde a
[ai , bi ), luego
Para cada segmento, guardamos el valor de
Oi =
bO
i 1
mj O[ai , bi )
j=ai
Estructuras de datos
Estructuras de datos
Estructuras de datos
Estructuras de datos
Estructuras de datos