Məsələnin müəllifi: | Matvii Hrytsyna |
Hazırlayanlar: | Matvii Hrytsyna, Konstantyn Denysov |
Həll: | Matvii Hrytsyna |
İdeya
Gəlin massivini belə təyin edək — burada sağ element olduqda, üçlüklərin bütün mümkün minimal sol indeksləri arasında ən böyüyü. Başqa sözlə, \text{lft}[k] = i, əgər (i,j,k) hansısa düzgün üçlükdürsə və sağ indeksi olan bütün düzgün üçlüklər arasında ən böyük indeksdirsə. Həmçinin, hər belə üçün \text{ans}[k] = (j,k) massivini saxlayırıq — ilə birlikdə düzgün üçlük yaradan konkret indeks cütü. Belə cütlər arasında -nın ən kiçik qiymətinə malik olanı saxlayırıq.
Həmçinin massivini qururuq, burada
Onda (l,r) sorğusu üçün cavab yalnız və yalnız \text{pref\_max}[r] \ge l olduqda mövcuddur.
massivini necə hesablamaq olar
Massiv üzrə soldan sağa keçirik. Hər bir üçün onun sadə bölənlərinin massivini saxlayırıq. Həmçinin hər sadə üçün -ni bölən son iki indeksləri saxlayırıq:
— ən yaxın əvvəlki indeks;
— ikinci ən yaxın əvvəlki indeks.
Əgər belə indeks yoxdursa, \text{lst}[i][p] = -1.
İki halı nəzərdən keçirək.
Hal 1: Üç ədədin hamısının gcd-si
Bu halda həm , həm də ilə ortaq sadə bölən -yə malikdir. üzərində iterasiya edirik və əgər \text{lst}[1][p] \neq -1-dirsə, yəni indeksinin solunda -yə bölünən ən azı iki ədəd varsa, onda
Hal 2: Üç ədədin gcd-si
Tutaq ki, -nın ilə ortaq sadə böləni , ilə isə ortaq sadə böləni var. Bu halda hər sadə üçün -ni götürüb həmin mövqelərdəki ədədlərin gcd-sinin -dən böyük olub-olmadığını yoxlaya bilərik. Yəni əgər
və
onda
Sorğulara necə cavab vermək olar
Bir (l,r) sorğusu üçün cavabın mövcud olması üçün hansısa l \le k \le r üçün \text{lft}[k] \ge l şərti ödənməlidir. Başqa sözlə, cavab yalnız və yalnız
olduqda mövcuddur.
k < l olduqda \text{lft}[k] < l olduğuna görə, seqment üzrə maksimum əvəzinə prefiks üzrə maksimumu götürə bilərik. Qoy idx = \text{pref\_max}[r]. Əgər idx < l-dirsə, cavab yoxdur; əks halda üçlük kimi
götürə bilərik.
Mürəkkəblik
Eratosfen ələyindən istifadə etməklə, \le A = 2 \cdot 10^5 olan ədədlər üçün bütün sadə bölənləri O(A \log A) vaxtında əvvəlcədən hesablaya bilərik. massivini O(n d^2 \log A) vaxtında hesablayırıq, burada bir ədədin maksimum sadə bölənlərinin sayıdır. Verilən məhdudiyyətlərdə d \le 6 olduğuna görə, bu asanlıqla limitlərə sığır. Hər sorğunu vaxtında cavablandırırıq.
Beləliklə, ümumi mürəkkəblik O(A \log A + n d^2 \log A + q)-dir.
#include <bits/stdc++.h>
using namespace std;
const int MAXA = 200010;
const int MAXN = 400000;
vector<int> primes[MAXA];
void sieve() {
for (int i = 2; i <= MAXA; i++)
if (primes[i].empty()) {
for (int j = i; j < MAXA; j += i)
primes[j].push_back(i);
}
}
int main() {
sieve();
int n;
cin >> n;
vector<int> a(n);
for (auto& ai : a)
cin >> ai;
vector<pair<int, int>> ans(n, {-1, -1});
vector<int> pref_max(n + 1, -1), lft(n, -1);
vector<vector<int>> lst(2, vector<int>(MAXA, -1));
for (int i = 0; i < n; i++) {
int x = a[i];
for (auto p : primes[x])
if (lst[1][p] != -1) {
lft[i] = max(lft[i], lst[1][p]);
if (ans[lst[1][p]].first == -1)
ans[lst[1][p]] = {lst[0][p], i};
}
for (auto p1 : primes[x])
for (auto p2 : primes[x]) {
if (p1 == p2 || lst[0][p1] == lst[0][p2])
continue;
if (lst[0][p1] >= 0 && lst[0][p2] >= 0 &&
__gcd(a[lst[0][p1]], a[lst[0][p2]]) > 1 &&
min(lst[0][p1], lst[0][p2]) > lft[i]) {
lft[i] = min(lst[0][p1], lst[0][p2]);
if (ans[min(lst[0][p1], lst[0][p2])].first == -1)
ans[min(lst[0][p1], lst[0][p2])] =
{max(lst[0][p1], lst[0][p2]), i};
}
}
for (auto p : primes[x]) {
lst[1][p] = lst[0][p];
lst[0][p] = i;
}
}
for (int i = 1; i < n; i++)
pref_max[i] = max(pref_max[i - 1], lft[i]);
int q;
cin >> q;
while (q--) {
int l, r;
cin >> l >> r;
--l, --r;
int idx = pref_max[r];
if (idx < l) {
cout << -1 << '\n';
} else {
cout << ans[idx].first + 1 << ' '
<< ans[idx].second + 1 << ' '
<< idx + 1 << '\n';
}
}
}