Gəlin, minimum əməliyyat sayının başlanğıc massivini
növündəki arifmetik proqresiyaya çevirdiyini fərz edək
Açıq-aydın, m[0] \le x \le max(m[0], m[1], ..., m[n - 1]).
Biz sıralamanı
uyğun adlandırırıqsa, o zaman bu ardıcıllığın , yəni hər bir üçün -dən n - 1-ə qədər m[i] \le d[i] şərtini yerinə yetirildiyi halda, massiv tarixə qədər ola bilər.
Uyğun olan ardıcıllığın olduğu minimum qiymətini müəyyən etmək lazımdır. Bunu binary axtarış üsulu ilə etmək olar.
Məsələnin nümunəsi
Gəlin ilk testi nəzərdən keçirək. Minimum elementlər məbləğinə uyğun ardıcıllığın d = [x, x + 1, x + 2, ..., x + n - 1] olması fərz edək.
Açıq-aydın, m[0] = 3 ≤ x ≤ 11 = max(m[i]).
İkilik axtarış ilə növü uyğun ardıcıllığın olması üçün minimum qiymətini öyrənirik.
Məsələn, x = 6 olaraq ardıcıllığın uyğun olmayacaq, amma x = 8 isə uyğun olacaqdır.
İkinci testi nəzərdən keçirmək istəyirik. İkili axtarışı da 4 \le x \le 7 aralığında başlatırıq. Məsələn, artıq x = 4 zamanı ardıcıllıq uyğun olur.
Alqoritmin tətbiqi
Giriş ardıcıllığını massivində saxlayırıq. Arifmetik proqresiyanın ardıcıllığını, x, x + 1, x + 2, ..., x + n - 1 formatında, massivində saxlayırıq.
#define MAX 1000000
int m[MAX], d[MAX];Yoxla funksiyası massivində növünə görə ardıcıllığı yaratır
Əgər hər bir i~(0 \le i \le n - 1) üçün m[i] \le d[i] qeyri-bərabərliyi öyrənilirsə, sırası ardıcıllığından alınacaq, yəni ayrı-ayrı elementlərin artırılması yolu ilə. Bu halda sırası uyğun adlanır.
Əgər sırası uyğun olsa, Yoxla funksiyası qaytarır, əks halda — .
int check(int first)
{
for (int i = 0; i < n; i++)
d[i] = first++;
for (int i = 0; i < n; i++)
if (m[i] > d[i]) return 0;
return 1;
}Proqramın əsas hissəsi. Giriş mənimliyinə oxuyuruq. massivində maksimum qiyməti hesablayırıq.
scanf("%d", &n);
mx = 0;
for (i = 0; i < n; i++)
{
scanf("%d", &m[i]);
if (m[i] > mx) mx = m[i];
}
start = m[0];
end = mx;İkili axtarışı qiymətində [start; end] = [m[0]; mx] aralığında başlatırıq.
Minimum qiymətini tapırıq ki, x, x + 1, x + 2, ..., x + n - 1 ardıcıllığını əldə etmək mümkün olsun m[0], m[1], ..., m[n - 1] massivindən.
while (start < end)
{
mid = (start + end) / 2;
if (check(mid))
end = mid;
else
start = mid + 1;
}Əldə etmək istədiyimiz arifmetik proqresiyanı yaradırıq.
for (i = 0; i < n; i++)
d[i] = start++;Minimum əməliyyat sayı hesablanır ki, proqresiyanı əldə etmək mümükün olsun.
op = 0;
for (int i = 0; i < n; i++)
op += (d[i] - m[i]);Nəticəni çıxarırıq.
printf("%lld\n", op);