Нехай масив містить вихідну перестановку. Побудуємо масив такий, що:
Наприклад, якщо
то
Відповідь на запит — це a[RMQa[u..v]].
Приклад
Розглянемо вхідну перестановку, задану масивом , і побудуємо допоміжний масив на її основі.
Наприклад, число знаходиться на позиції у перестановці (тобто b[9] = 1). Тому покладемо a[1] = 9.
Тепер розглянемо запит (a, b) = (2, 4). Число знаходиться на позиції , число — на позиції , а число — на позиції . Таким чином, у масиві елементи з індексами та рівні та відповідно — це позиції чисел та у вихідному масиві .
Залишається знайти мінімальне значення у підмасиві . Воно дорівнює (мінімум серед та ). Отже, відповідь — позиція .
Реалізація алгоритму
Оголосимо масив , де mas[i][j] зберігатиме індекс мінімального елемента на відрізку (i, ..., i + 2^j - 1). Оголосимо допоміжні масиви та .
#define DIM1 100010
#define DIM2 17
int mas[DIM1][DIM2];
int a[DIM1], b[DIM1];Функція Build_RMQ_Array будує масив на основі масиву таким чином, що
void Build_RMQ_Array(int *b)
{
int i, j;
for (i = 1; i <= n; i++) mas[i][0] = b[i];
for (j = 1; 1 << j <= n; j++)
for (i = 1; i + (1 << j) - 1 <= n; i++)
mas[i][j] = min(mas[i][j - 1], mas[i + (1 << (j - 1))][j - 1]);
}Функція RMQ повертає мінімальне значення на відрізку (b_i, b_{i+1}, ..., b_j) за час .
int RMQ(int i, int j)
{
int k = 0;
while ((1 << (k + 1)) <= j - i + 1) k++;
return min(mas[i][k],mas[j - (1<<k) + 1][k]);
}Зчитаємо вхідні дані та збережемо перестановку у масиві .
scanf("%d %d",&n,&q);
for (i = 1; i <= n; i++) scanf("%d",&b[i]);Побудуємо масив .
for (i = 1; i <= n; i++) a[b[i]] = i;Виконаємо попередню обробку для підтримки запитів .
Build_RMQ_Array(a);Для кожного запиту обчислимо та виведемо відповідь.
for (i = 0; i < q; i++)
{
scanf("%d %d",&u,&v);
printf("%d\n",RMQ(u,v));
}Реалізація на Java
import java.util.*;
public class Main
{
private final static int DIM1 = 100010;
private final static int DIM2 = 17;
static int[] a = new int[DIM1];
static int[] b = new int[DIM1];
static int[][] mas = new int[DIM1][DIM2];
static int min(int a, int b)
{
return (a < b) ? a : b;
}
static void Build_RMQ_Array(int[] b, int n)
{
int i, j;
for (i = 1; i <= n; i++) mas[i][0] = b[i];
for (j = 1; 1 << j <= n; j++)
for (i = 1; i + (1 << j) - 1 <= n; i++)
mas[i][j] =
min(mas[i][j - 1], mas[i + (1 << (j - 1))][j - 1]);
}
static int RMQ(int i, int j)
{
int k = 0;
while ((1 << (k + 1)) <= j - i + 1) k++;
return min(mas[i][k],mas[j - (1<<k) + 1][k]);
}
public static void main(String[] args)
{
Scanner con = new Scanner(System.in);
int i, n = con.nextInt(),
q = con.nextInt();
for (i = 1; i <= n; i++) b[i] = con.nextInt();
for (i = 1; i <= n; i++) a[b[i]] = i;
Build_RMQ_Array(a, n);
for(i = 0; i < q; i++)
{
int u = con.nextInt();
int v = con.nextInt();
System.out.println(RMQ(u,v));
}
}
}