Cod sursa(job #156125)

Utilizator marcelcodreaCodrea Marcel marcelcodrea Data 12 martie 2008 12:59:15
Problema Range minimum query Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 1.75 kb
// Se da un vector si doi indici
// Sa se determine pozitia elementului minim situat intre cei doi indici.
// Rezolvare cu arbore de intervale

#include <stdio.h>

long n, i, a[100002], m[1000000], s, d,mm;

void initai (int nod, int b, int e, int n) { // initializarea arborelui de intervale
  if (b == e) // begin, end
    m[nod] = b;
  else {
    initai (2*nod,           b, (b+e)/2, n);
    initai (2*nod+1, (b+e)/2+1,       e, n);
    if (a[m[2*nod]] <= a[m[2*nod+1]]) // Comparam minimele din subarborii fiilor.
      m[nod] = m[2*nod];
    else
      m[nod] = m[2*nod+1];
  }
}
int cerere (int nod, int b, int e, int s, int d) {
  int mins, mind;

  if (d < b || e < s)   // Intervalul curent si cel de cautare nu se intersecteaza
    return -1;
  if (s <= b && e <= d) // Intervalul curent este in interiorul intervalului de cautare
    return m[nod];
  else {
    mins = cerere (2*nod,           b, (b+e)/2, s, d); // minimul din stanga
    mind = cerere (2*nod+1, (b+e)/2+1,       e, s, d); // minimul din dreapta
    if (mins == -1)
      return mind;
		if (mind == -1)
      return mins;
    if (a[mins] <= a[mind])
      return mins;
    else
      return mind;
  }
}
int main() {
	freopen("rmq.in","r",stdin);
	freopen("rmq.out","w",stdout);
	scanf("%ld %ld",&n,&mm);
	for (i = 1; i <= n; i++) {
		scanf("%ld",&a[i]);
	}
	initai (1, 1, n, n);
	for (i = 1; i <= mm; i++)
	{
			scanf("%ld %ld",&s,&d);
			printf("%ld\n",a[cerere(1, 1, n, s, d)]);
	}
  return 0;
}

/*
Cazurile posibile in cerere:
( ) [   ]       caz 1
s d b   e

 (  [ ) ]       caz 3
 s  b d e

 (  [   ] )     caz 2
 s  b   e d

    [ ()]       caz 3
    b sde

    [ ( ] )     caz 3
    b s e d

    [   ] ()    caz 1
    b   e sd
*/