Problem:
Greatest of the Greatest Common Divisors
You are given a sequence of integers and a number of intervals in the sequence. The intervals are specified by their leftmost and rightmost positions. An interval consisting of $k$ integers has $k(k − 1)/2$ pairs of integers at different positions, which have their greatest common divisors. For each given interval, find the greatest one among such greatest common divisors.
For example, when the sequence is ($a_1, . . . , a_6) = (10, 20, 30, 40, 50, 60)$, and the whole sequence is specified as the interval, the following 15 pairs of two integers at different positions $x$ and $y$, and their greatest common divisors should be considered.
x
1
1
1
1
1
2
2
2
2
3
3
3
4
4
5
y
2
3
4
5
6
3
4
5
6
4
5
6
5
6
6
ax
10
10
10
10
10
20
20
20
20
30
30
30
40
40
50
ay
20
30
40
50
60
30
40
50
60
40
50
60
50
60
60
gcd(ax, ay)
10
10
10
10
10
10
20
10
20
10
10
30
10
20
10
The greatest of the greatest common divisors of the 15 pairs is $gcd(30, 60) = 30$, in this case.
Input
The input consists of a single test case of the following format.
$n$
$a_1$ ... $a_n$
$q$
$l_1$ $r_1$
$\vdots$
$l_q$ $r_q$
The first line contains an integer n, which is the number of integers in the given sequence, satisfying $2 \leq n \leq 10^5$. The second line contains n positive integers a1 through an, specifying the sequence. None of them exceeds $10^5$.
The third line contains a positive integer $q$, specifying the number of intervals in the sequence to be considered, which does not exceed $10^5$. It is followed by $q$ lines, each specifying an interval in the sequence to be considered. The $i$-th line of them has two integers, $l_i$ and $r_i$ ($1 \leq l_i < r_i \leq n$), specifying the interval $a_{l_i}$ through $a_{r_i}$ in the sequence.
Output
Output $q$ lines, the $i$-th line of which should have the greatest of the greatest common divisors of all pairs in the interval specified by $l_i$ and $r_i$.
Sample Input 1
6
10 20 30 40 50 60
3
1 6
2 5
4 5
Sample Output 1
30
20
10
Sample Input 2
10
13 2 35 4 13 2 5 1 7 4
5
1 4
4 10
3 8
3 9
1 10
Sample Output 2
2
4
5
7
13

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll INF = 1LL << 60;
#define rep(i, a) for(ll i = 0; i < (a); i++)
#define all(a) begin(a), end(a)
#define sz(a) (a).size()
bool chmin(auto &a, auto b) { return a > b ? a = b, 1 : 0; }
bool chmax(auto &a, auto b) { return a < b ? a = b, 1 : 0; }
template<class T> void out(T a) { cout << a << endl; }

using vll = vector<ll>;
using vvll = vector<vll>;
using pll = pair<ll, ll>;
using vpll = vector<pll>;
using ull = unsigned long long;

ll MX = 100000;
vvll ds;

class MoAlgorithm
{
    private:
    ll data_size;
    ll query_size;
    ll th;
    ll div_num;

    priority_queue<ll> pq;
    vll cnts;

    vll data;
    vpll query;
    vector<vector<pair<pll, ll>>> div_query;
    vll res;
    public:
    MoAlgorithm(vll input_data, vpll input_query) : data(input_data), query(input_query)
    {
        data_size = data.size();
        query_size = query.size();
        div_num = max(1LL, (ll)sqrt(query_size));
        th = 1 + (data_size - 1)/div_num;
        div_query = vector<vector<pair<pll, ll>>>(div_num);
        rep(i, query_size)
        {
            div_query[query[i].first/th].emplace_back(pll{query[i].second, query[i].first}, i);
        }
        rep(i, div_num)
        {
            if(i % 2 == 0) sort(all(div_query[i]));
            else sort(all(div_query[i]), greater<pair<pll, ll>>());
            rep(j, div_query[i].size())
            {
                swap(div_query[i][j].first.first, div_query[i][j].first.second);
            }
        }
        ResClear();
        Clear();
        ll l = 0, r = 0;
        rep(i, div_num)
        {
            rep(j, div_query[i].size())
            {
                while(r < div_query[i][j].first.second)
                {
                    InsertData(r);
                    r++;
                }
                while(l > div_query[i][j].first.first)
                {
                    InsertData(l - 1);
                    l--;
                }
                while(l < div_query[i][j].first.first)
                {
                    DeleteData(l);
                    l++;
                }
                while(r > div_query[i][j].first.second)
                {
                    DeleteData(r-1);
                    r--;
                }
                res[div_query[i][j].second] = Calc();
            }
        }
    }

    void ResClear()
    {
        res = vector<ll>(query_size, 0);
    }

    void Clear()
    {
        cnts = vll(MX + 1, 0);
    }

    void InsertData(ll id)
    {
        ll num = data[id];
        for(auto d : ds[num])
        {
            cnts[d]++;
            if(cnts[d] == 2) pq.emplace(d);
        }
    }

    void DeleteData(ll id)
    {
        ll num = data[id];
        for(auto d : ds[num])
        {
            cnts[d]--;
        }
    }

    ll Calc()
    {
        while(!pq.empty() && cnts[pq.top()] < 2) pq.pop();
        return pq.empty() ? 1LL : pq.top();
    }

    vll Ans()
    {
        return res;
    }
};

int main()
{
    ll N; cin >> N;
    vll A(N);
    rep(i, N) cin >> A[i];
    MX = *max_element(all(A));
    ds.resize(MX + 1);
    for(ll n = 1; n <= MX; n++)
    {
        for(ll m = n; m <= MX; m += n) ds[m].emplace_back(n);
    }
    ll Q; cin >> Q;
    vpll querys(Q);
    rep(i, Q)
    {
        ll l, r; cin >> l >> r;
        l--;
        querys[i] = {l, r};
    }
    MoAlgorithm Mo(A, querys);
    auto ans = Mo.Ans();
    rep(i, Q) cout << ans[i] << endl;
}
accuracy: 1
time_ms: 1410
memory_kb: 49676
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;

int segL[1<<18];

void update(int pos) {
    if (segL[pos +(1<<17)] == 0) {
        segL[pos +(1<<17)] = pos;
    }else {
        segL[pos +(1<<17)] = 0;
    }
    int id = (pos +(1<<17))/2;
    while (id != 0) {
        segL[id]=max(segL[id<<1],segL[(id<<1)+1]);
        id>>=1;
    }
}


int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    vector<int> D[100001];
    for (int cur=1;cur<=100000;cur++) {
        for (int i=1;i * i <= cur;i++) {
            if (cur % i == 0) {
                D[cur].push_back(i);
                if (cur != i * i)D[cur].push_back(cur / i);
            }
        }
    }
    vector<pair<pair<int,int>,int>>M[317];
    int N;
    cin>>N;
    int A[100001];
    for (int i=1;i<=N;i++) {
        cin>>A[i];
    }
    int Q;
    cin>>Q;
    for (int i=0;i<Q;i++) {
        int L,R;
        cin>>L>>R;
        M[R/317].push_back(make_pair(make_pair(L,R),i));
    }
    int nowL = 1;
    int nowR = 1;
    int C[100001] ={0};
    for (int i =0;i<D[A[1]].size();i++) {
        C[D[A[1]][i]]++;
    }
    int ans[100000];
    for (int i=0;i<317;i++) {
        sort(M[i].begin(),M[i].end());
        for (int j=0;j<M[i].size();j++) {
            while (nowL > M[i][j].first.first) {
                nowL--;
                for (int k =0;k<D[A[nowL]].size();k++) {
                    C[D[A[nowL]][k]]++;
                    if(C[D[A[nowL]][k]] == 2)update(D[A[nowL]][k]);
                }
            }
            while (nowL < M[i][j].first.first) {
                for (int k =0;k<D[A[nowL]].size();k++) {
                    C[D[A[nowL]][k]]--;
                    if(C[D[A[nowL]][k]] == 1)update(D[A[nowL]][k]);
                }
                nowL++;
            }
            while (nowR > M[i][j].first.second) {
                for (int k =0;k<D[A[nowR]].size();k++) {
                    C[D[A[nowR]][k]]--;
                    if(C[D[A[nowR]][k]] == 1)update(D[A[nowR]][k]);
                }
                nowR--;
            }
            while (nowR < M[i][j].first.second) {
                nowR++;
                for (int k =0;k<D[A[nowR]].size();k++) {
                    C[D[A[nowR]][k]]++;
                    if(C[D[A[nowR]][k]] == 2)update(D[A[nowR]][k]);
                }
            }
            ans[M[i][j].second] = segL[1];
        }
    }

    for (int i=0;i<Q;i++) {
        cout<<ans[i]<<"\n";
    }

}
accuracy: 1
time_ms: 2520
memory_kb: 16876
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    vector<int> D[100001];
    for (int cur=1;cur<=100000;cur++) {
        for (int i=1;i * i <= cur;i++) {
            if (cur % i == 0) {
                D[cur].push_back(i);
                if (cur != i * i)D[cur].push_back(cur / i);
            }
        }
    }
    vector<pair<pair<int,int>,int>>M[317];
    int N;
    cin>>N;
    int A[100001];
    for (int i=1;i<=N;i++) {
        cin>>A[i];
    }
    int Q;
    cin>>Q;
    for (int i=0;i<Q;i++) {
        int L,R;
        cin>>L>>R;
        M[R/317].push_back(make_pair(make_pair(L,R),i));
    }
    int nowL = 1;
    int nowR = 1;
    int C[100001] ={0};
    for (int i =0;i<D[A[1]].size();i++) {
        C[D[A[1]][i]]++;
    }
    set<int>SS;
    int ans[100000];
    for (int i=0;i<317;i++) {
        sort(M[i].begin(),M[i].end());
        for (int j=0;j<M[i].size();j++) {
            while (nowL < M[i][j].first.first) {
                for (int k =0;k<D[A[nowL]].size();k++) {
                    C[D[A[nowL]][k]]--;
                    if(C[D[A[nowL]][k]] == 1)SS.erase(D[A[nowL]][k]);
                }
                nowL++;
            }
            while (nowR > M[i][j].first.second) {
                for (int k =0;k<D[A[nowR]].size();k++) {
                    C[D[A[nowR]][k]]--;
                    if(C[D[A[nowR]][k]] == 1)SS.erase(D[A[nowR]][k]);
                }
                nowR--;
            }
            while (nowR < M[i][j].first.second) {
                nowR++;
                for (int k =0;k<D[A[nowR]].size();k++) {
                    C[D[A[nowR]][k]]++;
                    if(C[D[A[nowR]][k]] == 2)SS.insert(D[A[nowR]][k]);
                }
            }
            auto itr = SS.end();
            itr--;
            ans[M[i][j].second] = (*itr);
        }
    }

    for (int i=0;i<Q;i++) {
        cout<<ans[i]<<"\n";
    }

}
accuracy: 0.018867924528301886
time_ms: 980
memory_kb: 15800
final_rank: 20

code_snippet: /*
 *   author : cellul4r
 */
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pi;
typedef pair<ll,ll> pl;
typedef pair<ld,ld> pd;
#define all(x) x.begin(), x.end()
const char nl = '\n';
const int N =1e5+1;
const int INF = 1e9+7;
const ll LINF = 1e18+7;

void setIO(string);
struct segtree {

    int t[4*N];

    int f(int a, int b) { return max(a,b); }

    void update(int node, int l, int r, int idx, int val) {
        if(l == r) {
            t[node] = f(t[node],val);
            return;
        }

        int mid = (l + r) >> 1;
        if(idx <= mid) {
            update(node<<1,l,mid,idx,val);
        } else {
            update(node<<1|1,mid+1,r,idx,val);
        }
        t[node] = f(t[node<<1],t[node<<1|1]);
    }

    int query(int node, int l, int r, int L, int R) {
        if(l > R || r < L) return 1;
        if(l >= L && r <= R) {
            return t[node];
        }
        int mid = (l + r) >> 1;
        return f(query(node<<1,l,mid,L,R), query(node<<1|1,mid+1,r,L,R));
    }
};
int n,q;
// trick each we gradually increase the range query of R,R+1,...
// then when we go to that range R we have to know what value divisor does it has
// where is the last position of this divisor j we have seen
// at last[r] we have this divisor j we must find some another
// to get this gcd value = j
// just save it in last[r]
// then find max in range query[l,r]
vector<pi> save[N], query[N];
vector<int> divi[N];
int idx[N];
int a[N], ans[N];
void solve(){

    cin>>n;
    for(int i = 0; i < n; i++) {
        cin>>a[i];
    }

    cin>>q;
    for(int i = 0; i < q; i++) {
        int l, r; cin>>l>>r;
        l--,r--;
        query[r].push_back({l,i});
    }

    // save all divisor in O(nlogn)
    for(int i = 1; i < N; i++) {
        for(int j = i; j < N; j += i) {
            // j divisible by i
            divi[j].push_back(i);
        }
    }

    // create save[N] for at pos i each divisor j where does the last pos before this occur to get the gcd
    memset(idx, -1, sizeof idx);
    for(int i = 0; i < n; i++) {
        for(auto &j : divi[a[i]]) {
            // only save value divisor j in increasing position 
            if(idx[j] != -1) {
                save[i].push_back(make_pair(idx[j], j));
            }
            idx[j] = i;
        }
    }

    segtree seg;
    for(int r = 0; r < n; r++) {
        for(auto& [i, j] : save[r]) {
            seg.update(1,0,n-1,i,j);
        }

        for(auto &[l, i] : query[r]) {
            ans[i] = seg.query(1,0,n-1,l,r);            
        }
    }

    for(int i = 0; i < q; i++) {
        cout << ans[i] << nl;
    }
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t = 1;

    //setIO("");
    //cin>>t;
    while(t--)solve();

    return 0;
}

void setIO(string s) {
    (void)!freopen((s + ".in").c_str(), "r", stdin);
    (void)!freopen((s + ".out").c_str(), "w", stdout);
}
accuracy: 1
time_ms: 590
memory_kb: 123388
final_rank: 10

code_snippet: /*
 *   author : cellul4r
 */
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pi;
typedef pair<ll,ll> pl;
typedef pair<ld,ld> pd;
#define all(x) x.begin(), x.end()
const char nl = '\n';
const int N =1e5+1;
const int INF = 1e9+7;
const ll LINF = 1e18+7;

void setIO(string);
struct segtree {

    int t[4*N];

    int f(int a, int b) { return max(a,b); }

    void update(int node, int l, int r, int idx, int val) {
        if(l == r) {
            t[node] = f(t[node],val);
            return;
        }

        int mid = (l + r) >> 1;
        if(idx <= mid) {
            update(node<<1,l,mid,idx,val);
        } else {
            update(node<<1|1,mid+1,r,idx,val);
        }
        t[node] = f(t[node<<1],t[node<<1|1]);
    }

    int query(int node, int l, int r, int L, int R) {
        if(l > R || r < L) return 1;
        if(l >= L && r <= R) {
            return t[node];
        }
        int mid = (l + r) >> 1;
        return f(query(node<<1,l,mid,L,R), query(node<<1|1,mid+1,r,L,R));
    }
};
int n,q;
// trick each we gradually increase the range query of R,R+1,...
// then when we go to that range R we have to know what value divisor does it has
// where is the last position of this divisor j we have seen
// at last[r] we have this divisor j we must find some another
// to get this gcd value = j
// just save it in last[r]
// then find max in range query[l,r]
vector<pi> save[N], query[N];
vector<int> divi[N];
int idx[N];
int a[N], ans[N];
void solve(){

    cin>>n;
    for(int i = 0; i < n; i++) {
        cin>>a[i];
    }

    cin>>q;
    for(int i = 0; i < q; i++) {
        int l, r; cin>>l>>r;
        l--,r--;
        query[r].push_back({l,i});
    }

    // save all divisor in O(nlogn)
    for(int i = 1; i < N; i++) {
        for(int j = i; j < N; j += i) {
            // j divisible by i
            divi[j].push_back(i);
        }
    }

    for(int i = 1; i < N; i++) reverse(all(divi[i]));
    // create save[N] for at pos i each divisor j where does the last pos before this occur to get the gcd
    memset(idx, -1, sizeof idx);
    for(int i = 0; i < n; i++) {
        for(auto &j : divi[a[i]]) {
            // only save value divisor j in increasing position 
            if(idx[j] != -1) {
                save[i].push_back(make_pair(idx[j], j));
            }
            idx[j] = i;
        }
    }

    segtree seg;
    for(int r = 0; r < n; r++) {
        for(auto& [i, j] : save[r]) {
            seg.update(1,0,n-1,i,j);
        }

        for(auto &[l, i] : query[r]) {
            ans[i] = seg.query(1,0,n-1,l,r);            
        }
    }

    for(int i = 0; i < q; i++) {
        cout << ans[i] << nl;
    }
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t = 1;

    //setIO("");
    //cin>>t;
    while(t--)solve();

    return 0;
}

void setIO(string s) {
    (void)!freopen((s + ".in").c_str(), "r", stdin);
    (void)!freopen((s + ".out").c_str(), "w", stdout);
}
accuracy: 1
time_ms: 600
memory_kb: 123424
final_rank: 11

code_snippet: /*
 *   author : cellul4r
 */
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pi;
typedef pair<ll,ll> pl;
typedef pair<ld,ld> pd;
#define all(x) x.begin(), x.end()
const char nl = '\n';
const int N =1e5+1;
const int INF = 1e9+7;
const ll LINF = 1e18+7;

void setIO(string);
struct segtree {

    int t[4*N];

    int f(int a, int b) { return max(a,b); }

    void update(int node, int l, int r, int idx, int val) {
        if(l == r) {
            t[node] = f(t[node],val);
            return;
        }

        int mid = (l + r) >> 1;
        if(idx <= mid) {
            update(node<<1,l,mid,idx,val);
        } else {
            update(node<<1|1,mid+1,r,idx,val);
        }
        t[node] = f(t[node<<1],t[node<<1|1]);
    }

    int query(int node, int l, int r, int L, int R) {
        if(l > R || r < L) return 1;
        if(l >= L && r <= R) {
            return t[node];
        }
        int mid = (l + r) >> 1;
        return f(query(node<<1,l,mid,L,R), query(node<<1|1,mid+1,r,L,R));
    }
};
int n,q;
// trick each we gradually increase the range query of R,R+1,...
// then when we go to that range R we have to know what value divisor does it has
// where is the last position of this divisor j we have seen
// at last[r] we have this divisor j we must find some another
// to get this gcd value = j
// just save it in last[r]
// then find max in range query[l,r]
vector<pi> save[N], query[N];
vector<int> divi[N];
int idx[N];
int a[N], ans[N];
void solve(){

    cin>>n;
    for(int i = 0; i < n; i++) {
        cin>>a[i];
    }

    cin>>q;
    for(int i = 0; i < q; i++) {
        int l, r; cin>>l>>r;
        l--,r--;
        query[r].push_back({l,i});
    }

    // save all divisor in O(nlogn)
    for(int i = 1; i < N; i++) {
        for(int j = i; j < N; j += i) {
            // j divisible by i
            divi[j].push_back(i);
        }
    }

    for(int i = 1; i < N; i++) reverse(all(divi[i]));
    // create save[N] for at pos i each divisor j where does the last pos before this occur to get the gcd
    memset(idx, -1, sizeof idx);
    for(int i = 0; i < n; i++) {
        for(auto &j : divi[a[i]]) {
            // only save value divisor j in increasing position 
            if(idx[j] != -1) {
                if(save[i].empty() || save[i].back().first < idx[j]) {
                    save[i].push_back(make_pair(idx[j], j));
                }
            }
            idx[j] = i;
        }
    }

    segtree seg;
    for(int r = 0; r < n; r++) {
        for(auto& [i, j] : save[r]) {
            seg.update(1,0,n-1,i,j);
        }

        for(auto &[l, i] : query[r]) {
            ans[i] = seg.query(1,0,n-1,l,r);            
        }
    }

    for(int i = 0; i < q; i++) {
        cout << ans[i] << nl;
    }
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t = 1;

    //setIO("");
    //cin>>t;
    while(t--)solve();

    return 0;
}

void setIO(string s) {
    (void)!freopen((s + ".in").c_str(), "r", stdin);
    (void)!freopen((s + ".out").c_str(), "w", stdout);
}
accuracy: 1
time_ms: 130
memory_kb: 31528
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;

int n, q;
const int MAXN = 1e5 + 5;
int a[MAXN];

struct Node {
    int mx1, mx2; // largest and second largest
    Node(int _mx1 = 0, int _mx2 = 0) : mx1(_mx1), mx2(_mx2) {}
};

// merge two nodes: pick the top 2 numbers
Node merge(Node left, Node right) {
    vector<int> v = {left.mx1, left.mx2, right.mx1, right.mx2};
    sort(v.rbegin(), v.rend()); // descending
    return Node(v[0], v[1]);
}

Node seg[4*MAXN];

// build segment tree
void build(int idx, int l, int r) {
    if (l == r) {
        seg[idx] = Node(a[l], 0);
        return;
    }
    int mid = (l+r)/2;
    build(2*idx, l, mid);
    build(2*idx+1, mid+1, r);
    seg[idx] = merge(seg[2*idx], seg[2*idx+1]);
}

// query [ql, qr]
Node query(int idx, int l, int r, int ql, int qr) {
    if (qr < l || r < ql) return Node(0,0);
    if (ql <= l && r <= qr) return seg[idx];
    int mid = (l+r)/2;
    Node left = query(2*idx, l, mid, ql, qr);
    Node right = query(2*idx+1, mid+1, r, ql, qr);
    return merge(left, right);
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> n;
    for (int i=0;i<n;i++) cin >> a[i];

    build(1,0,n-1);

    cin >> q;
    for (int i=0;i<q;i++) {
        int l,r;
        cin >> l >> r;
        l--; r--; // 0-indexed
        Node res = query(1,0,n-1,l,r);
        cout << __gcd(res.mx1, res.mx2) << "\n";
    }

    return 0;
}
accuracy: 0.018867924528301886
time_ms: 100
memory_kb: 6892
final_rank: 18

code_snippet: #include"atcoder/segtree"
#include<bits/stdc++.h>
using namespace std;
#define rep(i,n) for(int i=0;i<(int)(n);++i)
vector<int>get_divisors(int n){
  vector<int>ret;
  for(int i=1;i*i<=n;++i){
    if(n%i!=0)continue;
    ret.emplace_back(i);
    if(i*i!=n)ret.emplace_back(n/i);
  }
  return ret;
}
int op(int a,int b){
  return max(a,b);
}
int e(){
  return 0;
}
int n,a[1<<17],q,l[1<<17],r[1<<17];
vector<pair<int,int>>li[1<<17];
int ans[1<<17];
int pos[1<<17];
atcoder::segtree<int,op,e>seg(1<<17);
signed main(){
  cin.tie(0)->sync_with_stdio(0);
  rep(i,1<<17)pos[i]=-1;

  cin>>n;
  rep(i,n)cin>>a[i];
  cin>>q;
  rep(i,q){
    cin>>l[i]>>r[i],--l[i];
    li[r[i]].emplace_back(l[i],i);
  }
  rep(i,n){
    auto div=get_divisors(a[i]);
    for(const auto&d:div){
      if(pos[d]!=-1){
        seg.set(pos[d],max(d,seg.get(pos[d])));
      }
      pos[d]=i;
    }
    for(auto[ql,qi]:li[i+1]){
      ans[qi]=seg.prod(ql,i+1);
    }
  }
  rep(i,q)cout<<ans[i]<<'\n';
}
accuracy: 1
time_ms: 300
memory_kb: 12492
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;
template<class T> bool chmin(T& a, T b) { return a > b ? a = b, true : false; }
template<class T> bool chmax(T& a, T b) { return a < b ? a = b, true : false; }
template<typename T>
concept Iterable = requires(T t) { std::begin(t); std::end(t); };
template<typename T>
	requires Iterable<T> && (!is_same_v<T, string>)
ostream& operator<<(ostream& os, const T& container) { for (auto& element : container) os << element << ' '; return os; }
template<typename R>
	requires ranges::range<R> && (!is_same_v<decay_t<R>, string>) && (!is_same_v<decay_t<R>, const char*>)
ostream& operator<<(ostream& os, R&& range) { for (auto& element : range)os << element << ' '; return os; }
template<typename T>
	requires Iterable<T> && (!is_same_v<T, string>)
istream& operator>>(std::istream& is, T& container) { for (auto& e : container)is >> e; return is; }
using ll = long long;
using ull = unsigned long long;
using uint = unsigned int;
template<class T = ll> struct Edge {
	int to;
	T weight;
	bool operator==(Edge e) { return this->to == e.to and this->weight == e.weight; }
	bool operator<(Edge e) { return this->to == e.to ? this->weight < e.weight : this->to < e.to; }
};
#ifdef _DEBUG
#define SHOW(n) {const auto& _ret = n; cerr << #n << ": " << _ret << endl;}
#define MSG(x) cerr << x << endl;
#else
#define SHOW(n)
#define MSG(x)
#endif

////AtCoder Library 
//#include <atcoder/all>
//using namespace atcoder;
//using mint = modint998244353;
////using mint = modint1000000007;
////using mint1 = dynamic_modint<0>;
////using mint = modint;
////mint::set_mod();
//istream& operator>>(istream& is, mint& x) { ll r; is >> r; x = r; return is; }
//ostream& operator<<(ostream& os, mint& x) { os << x.val(); return os; }

//boost
//#include <boost/multiprecision/cpp_int.hpp>
//using namespace boost::multiprecision;
//using l3 = int128_t;

struct BIT {
	vector<ll> a;
	BIT(ll n) : a(n + 1) {}
	void add(ll i, ll x) {
		++i;
		while (i < a.size())a[i] += x, i += i & -i;
	}
	ll sum(ll r) {
		ll s = 0;
		while (r)s += a[r], r -= r & -r;
		return s;
	}
	ll sum(ll l, ll r) { return sum(r) - sum(l); }

	int lower_bound(ll w) {
		if (w <= 0)return 0;
		int x = 0, N = a.size() + 1;
		int lg = bit_width(unsigned(N)) - 1;
		for (int k = 1 << lg; k; k >>= 1) {
			if (x + k < a.size() and a[x + k] < w) {
				w -= a[x + k];
				x += k;
			}
		}
		return x;
	}
};

int main() {
	cin.tie(nullptr);
	ios::sync_with_stdio(false);

	int n;
	cin >> n;
	vector<int> a(n);
	cin >> a;

	int q;
	cin >> q;
	vector<int> l(q), r(q);
	for (int i = 0; i < q; ++i) {
		cin >> l[i] >> r[i];
		--l[i];
	}

	const int B = max<int>(1, n / sqrt(2.0 * q / 3));
	vector<int> idx(q);
	iota(idx.begin(), idx.end(), 0);
	ranges::sort(idx, [&](int i, int j) {
		if (l[i] / B == l[j] / B)return r[i] < r[j];
		else return l[i] < l[j];
		});

	vector<vector<int>> factor(n);
	for (int i = 0; i < n; ++i) {
		for (int j = 1; j * j <= a[i]; ++j) {
			if (a[i] % j == 0) {
				factor[i].push_back(j);
				if (j * j != a[i])factor[i].push_back(a[i] / j);
			}
		}
	}

	vector<int> cnt(1e5 + 1);

	BIT seg(1e5 + 1);

	int ssize = 0;
	int nl = 0, nr = 0;
	vector<int> res(q);
	for (int i : idx) {
		while (l[i] < nl) {
			--nl;
			for (auto d : factor[nl]) {
				cnt[d]++;
				if (cnt[d] == 2) {
					seg.add(d, 1);
					++ssize;
				}
			}
		}
		while (nr < r[i]) {
			for (auto d : factor[nr]) {
				cnt[d]++;
				if (cnt[d] == 2) {
					seg.add(d, 1);
					++ssize;
				}
			}
			nr++;
		}
		while (nl < l[i]) {
			for (auto d : factor[nl]) {
				cnt[d]--;
				if (cnt[d] == 1) {
					seg.add(d, -1);
					--ssize;
				}
			}
			nl++;
		}
		while (r[i] < nr) {
			--nr;
			for (auto d : factor[nr]) {
				cnt[d]--;
				if (cnt[d] == 1) {
					seg.add(d, -1);
					--ssize;
				}
			}
		}

		int j = seg.lower_bound(ssize);
		res[i] = j;
	}

	for (auto x : res)cout << x << endl;

	return 0;
}
accuracy: 1
time_ms: 1030
memory_kb: 60456
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
template<class T> bool chmin(T& a, T b) { return a > b ? a = b, true : false; }
template<class T> bool chmax(T& a, T b) { return a < b ? a = b, true : false; }
template<typename T>
concept Iterable = requires(T t) { std::begin(t); std::end(t); };
template<typename T>
	requires Iterable<T> && (!is_same_v<T, string>)
ostream& operator<<(ostream& os, const T& container) { for (auto& element : container) os << element << ' '; return os; }
template<typename R>
	requires ranges::range<R> && (!is_same_v<decay_t<R>, string>) && (!is_same_v<decay_t<R>, const char*>)
ostream& operator<<(ostream& os, R&& range) { for (auto& element : range)os << element << ' '; return os; }
template<typename T>
	requires Iterable<T> && (!is_same_v<T, string>)
istream& operator>>(std::istream& is, T& container) { for (auto& e : container)is >> e; return is; }
using ll = long long;
using ull = unsigned long long;
using uint = unsigned int;

struct BIT {
	vector<ll> a;
	BIT(ll n) : a(n + 1) {}
	void add(ll i, ll x) {
		++i;
		while (i < a.size())a[i] += x, i += i & -i;
	}
	ll sum(ll r) {
		ll s = 0;
		while (r)s += a[r], r -= r & -r;
		return s;
	}
	ll sum(ll l, ll r) { return sum(r) - sum(l); }

	int lower_bound(ll w) {
		if (w <= 0)return 0;
		int x = 0, N = a.size() + 1;
		int lg = bit_width(unsigned(N)) - 1;
		for (int k = 1 << lg; k; k >>= 1) {
			if (x + k <= N - 1 and a[x + k] < w) {
				w -= a[x + k];
				x += k;
			}
		}
		return x;
	}
};

int main() {
	cin.tie(nullptr);
	ios::sync_with_stdio(false);

	int n;
	cin >> n;
	vector<int> a(n);
	cin >> a;

	int q;
	cin >> q;
	vector<int> l(q), r(q);
	for (int i = 0; i < q; ++i) {
		cin >> l[i] >> r[i];
		--l[i];
	}

	const int B = max<int>(1, n / sqrt(2.0 * q / 3));
	vector<int> idx(q);
	iota(idx.begin(), idx.end(), 0);
	ranges::sort(idx, [&](int i, int j) {
		if (l[i] / B == l[j] / B)return r[i] < r[j];
		else return l[i] < l[j];
		});

	vector<vector<int>> factor(n);
	for (int i = 0; i < n; ++i) {
		for (int j = 1; j * j <= a[i]; ++j) {
			if (a[i] % j == 0) {
				factor[i].push_back(j);
				if (j * j != a[i])factor[i].push_back(a[i] / j);
			}
		}
	}

	vector<int> cnt(1e5 + 1);

	BIT seg(1e5 + 1);


	int ssize = 0;
	int nl = 0, nr = 0;
	vector<int> res(q);
	for (int i : idx) {
		while (l[i] < nl) {
			--nl;
			for (auto d : factor[nl]) {
				cnt[d]++;
				if (cnt[d] == 2) {
					seg.add(d, 1);
					++ssize;
				}
			}
		}
		while (nr < r[i]) {
			for (auto d : factor[nr]) {
				cnt[d]++;
				if (cnt[d] == 2) {
					seg.add(d, 1);
					++ssize;
				}
			}
			nr++;
		}
		while (nl < l[i]) {
			for (auto d : factor[nl]) {
				cnt[d]--;
				if (cnt[d] == 1) {
					seg.add(d, -1);
					--ssize;
				}
			}
			++nl;
		}
		while (r[i] < nr) {
			--nr;
			for (auto d : factor[nr]) {
				cnt[d]--;
				if (cnt[d] == 1) {
					seg.add(d, -1);
					--ssize;
				}
			}
		}

		int j = seg.lower_bound(ssize);
		res[i] = j;
	}

	for (auto x : res)cout << x << endl;

	return 0;
}
accuracy: 0.1320754716981132
time_ms: 1010
memory_kb: 60456
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;
template<class T> bool chmin(T& a, T b) { return a > b ? a = b, true : false; }
template<class T> bool chmax(T& a, T b) { return a < b ? a = b, true : false; }
template<typename T>
concept Iterable = requires(T t) { std::begin(t); std::end(t); };
template<typename T>
	requires Iterable<T> && (!is_same_v<T, string>)
ostream& operator<<(ostream& os, const T& container) { for (auto& element : container) os << element << ' '; return os; }
template<typename R>
	requires ranges::range<R> && (!is_same_v<decay_t<R>, string>) && (!is_same_v<decay_t<R>, const char*>)
ostream& operator<<(ostream& os, R&& range) { for (auto& element : range)os << element << ' '; return os; }
template<typename T>
	requires Iterable<T> && (!is_same_v<T, string>)
istream& operator>>(std::istream& is, T& container) { for (auto& e : container)is >> e; return is; }
using ll = long long;
using ull = unsigned long long;
using uint = unsigned int;

struct BIT {
	vector<ll> a;
	BIT(ll n) : a(n + 1) {}
	void add(ll i, ll x) {
		++i;
		while (i < a.size())a[i] += x, i += i & -i;
	}
	ll sum(ll r) {
		ll s = 0;
		while (r)s += a[r], r -= r & -r;
		return s;
	}
	ll sum(ll l, ll r) { return sum(r) - sum(l); }

	int lower_bound(ll w) {
		if (w <= 0)return 0;
		int x = 0, N = a.size() + 1;
		int lg = bit_width(unsigned(N)) - 1;
		for (int k = 1 << lg; k; k >>= 1) {
			if (x + k <= N - 1 and a[x + k] < w) {
				w -= a[x + k];
				x += k;
			}
		}
		return x;
	}
};

int main() {
	cin.tie(nullptr);
	ios::sync_with_stdio(false);

	int n;
	cin >> n;
	vector<int> a(n);
	cin >> a;

	int q;
	cin >> q;
	vector<int> l(q), r(q);
	for (int i = 0; i < q; ++i) {
		cin >> l[i] >> r[i];
		--l[i];
	}

	const int B = max<int>(1, n / sqrt(2.0 * q / 3));
	vector<int> idx(q);
	iota(idx.begin(), idx.end(), 0);
	ranges::sort(idx, [&](int i, int j) {
		if (l[i] / B == l[j] / B)return r[i] < r[j];
		else return l[i] < l[j];
		});

	vector<vector<int>> factor(n);
	for (int i = 0; i < n; ++i) {
		for (int j = 1; j * j <= a[i]; ++j) {
			if (a[i] % j == 0) {
				factor[i].push_back(j);
				if (j * j != a[i])factor[i].push_back(a[i] / j);
			}
		}
	}

	vector<int> cnt(1e5 + 1);

	BIT seg(1e5 + 1);

	int ssize = 0;
	int nl = 0, nr = 0;
	vector<int> res(q);
	for (int i : idx) {
		while (l[i] < nl) {
			--nl;
			for (auto d : factor[nl]) {
				cnt[d]++;
				if (cnt[d] == 2) {
					seg.add(d, 1);
					++ssize;
				}
			}
		}
		while (nr < r[i]) {
			for (auto d : factor[nr]) {
				cnt[d]++;
				if (cnt[d] == 2) {
					seg.add(d, 1);
					++ssize;
				}
			}
			nr++;
		}
		while (nl < l[i]) {
			for (auto d : factor[nl]) {
				cnt[d]--;
				if (cnt[d] == 1) {
					seg.add(d, -1);
					--ssize;
				}
			}
			++nl;
		}
		while (r[i] < nr) {
			++nr;
			for (auto d : factor[nr]) {
				cnt[d]--;
				if (cnt[d] == 1) {
					seg.add(d, -1);
					--ssize;
				}
			}
		}

		int j = seg.lower_bound(ssize);
		res[i] = j;
	}

	for (auto x : res)cout << x << endl;

	return 0;
}
accuracy: 0.018867924528301886
time_ms: 120
memory_kb: 60416
final_rank: 19

code_snippet: #pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")

#include <bits/stdc++.h>
using namespace std;

template<class S, class T> inline bool chmax(S &a, T b) { return (a < b ? a = b, 1 : 0); }
template<class S, class T> inline bool chmin(S &a, T b) { return (a > b ? a = b, 1 : 0); }

using pint = pair<int, int>;
using pll = pair<long long, long long>;
using tint = array<int, 3>;
using tll = array<long long, 3>;
using fint = array<int, 4>;
using fll = array<long long, 4>;
using vll = vector<long long>;
using ll = long long;
using u32 = unsigned int;
using u64 = unsigned long long;
using int128 = __int128;
using u128 = unsigned __int128;
template <class T>
using min_priority_queue = priority_queue<T, vector<T>, greater<T>>;

#define REP(i, a) for (long long i = 0; i < (long long)(a); i++)
#define REP2(i, a, b) for (long long i = a; i < (long long)(b); i++)
#define RREP(i, a) for (long long i = (a)-1; i >= (long long)(0); --i)
#define RREP2(i, a, b) for (long long i = (b)-1; i >= (long long)(a); --i)
#define EB emplace_back
#define PB push_back
#define MP make_pair
#define MT make_tuple
#define FI first
#define SE second
#define ALL(x) x.begin(), x.end()
#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl

// debug stream
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P)
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, deque<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, vector<vector<T> > P)
{ for (int i = 0; i < P.size(); ++i) { s << endl << P[i]; } return s << endl; }
template<class T> ostream& operator << (ostream &s, set<T> P)
{ for (auto it : P) { s << "<" << it << "> "; } return s; }
template<class T> ostream& operator << (ostream &s, multiset<T> P)
{ for (auto it : P) { s << "<" << it << "> "; } return s; }
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P)
{ for (auto it : P) { s << "<" << it.first << "->" << it.second << "> "; } return s; }



// BIT
template <class Abel> struct BIT {
    Abel UNITY_SUM = 0;
    vector<Abel> dat;
    
    // [0, n)
    BIT(int n, Abel unity = 0) : UNITY_SUM(unity), dat(n, unity) { }
    void init(int n) {
        dat.assign(n, UNITY_SUM);
    }
    
    // a is 0-indexed
    inline void add(int a, Abel x) {
        for (int i = a; i < (int)dat.size(); i |= i + 1)
            dat[i] = dat[i] + x;
    }
    
    // [0, a), a is 0-indexed
    inline Abel sum(int a) {
        Abel res = UNITY_SUM;
        for (int i = a - 1; i >= 0; i = (i & (i + 1)) - 1)
            res = res + dat[i];
        return res;
    }
    
    // [a, b), a and b are 0-indexed
    inline Abel sum(int a, int b) {
        return sum(b) - sum(a);
    }
    
    // debug
    void print() {
        for (int i = 0; i < (int)dat.size(); ++i)
            cout << sum(i, i + 1) << ",";
        cout << endl;
    }
};

// Segment Tree
template<class Monoid> struct SegmentTree {
    using Func = function<Monoid(Monoid, Monoid)>;

    // core member
    int N;
    Func OP;
    Monoid IDENTITY;
    
    // inner data
    int log, offset;
    vector<Monoid> dat;

    // constructor
    SegmentTree() {}
    SegmentTree(int n, const Func &op, const Monoid &identity) {
        init(n, op, identity);
    }
    SegmentTree(const vector<Monoid> &v, const Func &op, const Monoid &identity) {
        init(v, op, identity);
    }
    void init(int n, const Func &op, const Monoid &identity) {
        N = n;
        OP = op;
        IDENTITY = identity;
        log = 0, offset = 1;
        while (offset < N) ++log, offset <<= 1;
        dat.assign(offset * 2, IDENTITY);
    }
    void init(const vector<Monoid> &v, const Func &op, const Monoid &identity) {
        init((int)v.size(), op, identity);
        build(v);
    }
    void pull(int k) {
        dat[k] = OP(dat[k * 2], dat[k * 2 + 1]);
    }
    void build(const vector<Monoid> &v) {
        assert(N == (int)v.size());
        for (int i = 0; i < N; ++i) dat[i + offset] = v[i];
        for (int k = offset - 1; k > 0; --k) pull(k);
    }
    int size() const {
        return N;
    }
    Monoid operator [] (int i) const {
        return dat[i + offset];
    }
    
    // update A[i], i is 0-indexed, O(log N)
    void set(int i, const Monoid &v) {
        assert(0 <= i && i < N);
        int k = i + offset;
        dat[k] = v;
        while (k >>= 1) pull(k);
    }
    
    // get [l, r), l and r are 0-indexed, O(log N)
    Monoid prod(int l, int r) {
        assert(0 <= l && l <= r && r <= N);
        Monoid val_left = IDENTITY, val_right = IDENTITY;
        l += offset, r += offset;
        for (; l < r; l >>= 1, r >>= 1) {
            if (l & 1) val_left = OP(val_left, dat[l++]);
            if (r & 1) val_right = OP(dat[--r], val_right);
        }
        return OP(val_left, val_right);
    }
    Monoid all_prod() {
        return dat[1];
    }
    
    // get max r that f(get(l, r)) = True (0-indexed), O(log N)
    // f(IDENTITY) need to be True
    int max_right(const function<bool(Monoid)> f, int l = 0) {
        if (l == N) return N;
        l += offset;
        Monoid sum = IDENTITY;
        do {
            while (l % 2 == 0) l >>= 1;
            if (!f(OP(sum, dat[l]))) {
                while (l < offset) {
                    l = l * 2;
                    if (f(OP(sum, dat[l]))) {
                        sum = OP(sum, dat[l]);
                        ++l;
                    }
                }
                return l - offset;
            }
            sum = OP(sum, dat[l]);
            ++l;
        } while ((l & -l) != l);  // stop if l = 2^e
        return N;
    }

    // get min l that f(get(l, r)) = True (0-indexed), O(log N)
    // f(IDENTITY) need to be True
    int min_left(const function<bool(Monoid)> f, int r = -1) {
        if (r == 0) return 0;
        if (r == -1) r = N;
        r += offset;
        Monoid sum = IDENTITY;
        do {
            --r;
            while (r > 1 && (r % 2)) r >>= 1;
            if (!f(OP(dat[r], sum))) {
                while (r < offset) {
                    r = r * 2 + 1;
                    if (f(OP(dat[r], sum))) {
                        sum = OP(dat[r], sum);
                        --r;
                    }
                }
                return r + 1 - offset;
            }
            sum = OP(dat[r], sum);
        } while ((r & -r) != r);
        return 0;
    }
    
    // debug
    friend ostream& operator << (ostream &s, const SegmentTree &seg) {
        for (int i = 0; i < (int)seg.size(); ++i) {
            s << seg[i];
            if (i != (int)seg.size() - 1) s << " ";
        }
        return s;
    }
};

// Lazy Segment Tree
template<class Monoid, class Action> struct LazySegmentTree {
    // various function types
    using FuncMonoid = function<Monoid(Monoid, Monoid)>;
    using FuncAction = function<Monoid(Action, Monoid)>;
    using FuncComposition = function<Action(Action, Action)>;

    // core member
    int N;
    FuncMonoid OP;
    FuncAction ACT;
    FuncComposition COMP;
    Monoid IDENTITY_MONOID;
    Action IDENTITY_ACTION;
    
    // inner data
    int log, offset;
    vector<Monoid> dat;
    vector<Action> lazy;
    
    // constructor
    LazySegmentTree() {}
    LazySegmentTree(int n, const FuncMonoid op, const FuncAction act, const FuncComposition comp,
                    const Monoid &identity_monoid, const Action &identity_action) {
        init(n, op, act, comp, identity_monoid, identity_action);
    }
    LazySegmentTree(const vector<Monoid> &v,
                    const FuncMonoid op, const FuncAction act, const FuncComposition comp,
                    const Monoid &identity_monoid, const Action &identity_action) {
        init(v, op, act, comp, identity_monoid, identity_action);
    }
    void init(int n, const FuncMonoid op, const FuncAction act, const FuncComposition comp,
              const Monoid &identity_monoid, const Action &identity_action) {
        N = n, OP = op, ACT = act, COMP = comp;
        IDENTITY_MONOID = identity_monoid, IDENTITY_ACTION = identity_action;
        log = 0, offset = 1;
        while (offset < N) ++log, offset <<= 1;
        dat.assign(offset * 2, IDENTITY_MONOID);
        lazy.assign(offset * 2, IDENTITY_ACTION);
    }
    void init(const vector<Monoid> &v,
              const FuncMonoid op, const FuncAction act, const FuncComposition comp,
              const Monoid &identity_monoid, const Action &identity_action) {
        init((int)v.size(), op, act, comp, identity_monoid, identity_action);
        build(v);
    }
    void build(const vector<Monoid> &v) {
        assert(N == (int)v.size());
        for (int i = 0; i < N; ++i) dat[i + offset] = v[i];
        for (int k = offset - 1; k > 0; --k) pull_dat(k);
    }
    int size() const {
        return N;
    }
    
    // basic functions for lazy segment tree
    void pull_dat(int k) {
        dat[k] = OP(dat[k * 2], dat[k * 2 + 1]);
    }
    void apply_lazy(int k, const Action &f) {
        dat[k] = ACT(f, dat[k]);
        if (k < offset) lazy[k] = COMP(f, lazy[k]);
    }
    void push_lazy(int k) {
        apply_lazy(k * 2, lazy[k]);
        apply_lazy(k * 2 + 1, lazy[k]);
        lazy[k] = IDENTITY_ACTION;
    }
    void pull_dat_deep(int k) {
        for (int h = 1; h <= log; ++h) pull_dat(k >> h);
    }
    void push_lazy_deep(int k) {
        for (int h = log; h >= 1; --h) push_lazy(k >> h);
    }
    
    // setter and getter, update A[i], i is 0-indexed, O(log N)
    void set(int i, const Monoid &v) {
        assert(0 <= i && i < N);
        int k = i + offset;
        push_lazy_deep(k);
        dat[k] = v;
        pull_dat_deep(k);
    }
    Monoid get(int i) {
        assert(0 <= i && i < N);
        int k = i + offset;
        push_lazy_deep(k);
        return dat[k];
    }
    Monoid operator [] (int i) {
        return get(i);
    }
    
    // apply f for index i
    void apply(int i, const Action &f) {
        assert(0 <= i && i < N);
        int k = i + offset;
        push_lazy_deep(k);
        dat[k] = ACT(f, dat[k]);
        pull_dat_deep(k);
    }
    // apply f for interval [l, r)
    void apply(int l, int r, const Action &f) {
        assert(0 <= l && l <= r && r <= N);
        if (l == r) return;
        l += offset, r += offset;
        for (int h = log; h >= 1; --h) {
            if (((l >> h) << h) != l) push_lazy(l >> h);
            if (((r >> h) << h) != r) push_lazy((r - 1) >> h);
        }
        int original_l = l, original_r = r;
        for (; l < r; l >>= 1, r >>= 1) {
            if (l & 1) apply_lazy(l++, f);
            if (r & 1) apply_lazy(--r, f);
        }
        l = original_l, r = original_r;
        for (int h = 1; h <= log; ++h) {
            if (((l >> h) << h) != l) pull_dat(l >> h);
            if (((r >> h) << h) != r) pull_dat((r - 1) >> h);
        }
    }
    
    // get prod of interval [l, r)
    Monoid prod(int l, int r) {
        assert(0 <= l && l <= r && r <= N);
        if (l == r) return IDENTITY_MONOID;
        l += offset, r += offset;
        for (int h = log; h >= 1; --h) {
            if (((l >> h) << h) != l) push_lazy(l >> h);
            if (((r >> h) << h) != r) push_lazy(r >> h);
        }
        Monoid val_left = IDENTITY_MONOID, val_right = IDENTITY_MONOID;
        for (; l < r; l >>= 1, r >>= 1) {
            if (l & 1) val_left = OP(val_left, dat[l++]);
            if (r & 1) val_right = OP(dat[--r], val_right);
        }
        return OP(val_left, val_right);
    }
    Monoid all_prod() {
        return dat[1];
    }
    
    // get max r that f(get(l, r)) = True (0-indexed), O(log N)
    // f(IDENTITY) need to be True
    int max_right(const function<bool(Monoid)> f, int l = 0) {
        if (l == N) return N;
        l += offset;
        push_lazy_deep(l);
        Monoid sum = IDENTITY_MONOID;
        do {
            while (l % 2 == 0) l >>= 1;
            if (!f(OP(sum, dat[l]))) {
                while (l < offset) {
                    push_lazy(l);
                    l = l * 2;
                    if (f(OP(sum, dat[l]))) {
                        sum = OP(sum, dat[l]);
                        ++l;
                    }
                }
                return l - offset;
            }
            sum = OP(sum, dat[l]);
            ++l;
        } while ((l & -l) != l);  // stop if l = 2^e
        return N;
    }

    // get min l that f(get(l, r)) = True (0-indexed), O(log N)
    // f(IDENTITY) need to be True
    int min_left(const function<bool(Monoid)> f, int r = -1) {
        if (r == 0) return 0;
        if (r == -1) r = N;
        r += offset;
        push_lazy_deep(r - 1);
        Monoid sum = IDENTITY_MONOID;
        do {
            --r;
            while (r > 1 && (r % 2)) r >>= 1;
            if (!f(OP(dat[r], sum))) {
                while (r < offset) {
                    push_lazy(r);
                    r = r * 2 + 1;
                    if (f(OP(dat[r], sum))) {
                        sum = OP(dat[r], sum);
                        --r;
                    }
                }
                return r + 1 - offset;
            }
            sum = OP(dat[r], sum);
        } while ((r & -r) != r);
        return 0;
    }
    
    // debug stream
    friend ostream& operator << (ostream &s, LazySegmentTree seg) {
        for (int i = 0; i < (int)seg.size(); ++i) {
            s << seg[i];
            if (i != (int)seg.size() - 1) s << " ";
        }
        return s;
    }
    
    // dump
    void dump() {
        for (int i = 0; i <= log; ++i) {
            for (int j = (1 << i); j < (1 << (i + 1)); ++j) {
                cout << "{" << dat[j] << "," << lazy[j] << "} ";
            }
            cout << endl;
        }
    }
};



struct Node {
    vector<int> vec;
    int mex;
    Node() : mex(0) {}
    Node(const vector<int> &vec, int mex) : vec(vec), mex(mex) {}
    friend ostream& operator << (ostream &s, const Node &node) {
        return s << "(" << node.vec << ", " << node.mex << ")";
    }
};

int main() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);

    int N, Q;
    cin >> N;
    vector<int> A(N);
    REP(i, N) cin >> A[i];
    cin >> Q;
    vector<tint> qs(Q);
    REP(qid, Q) {
        cin >> qs[qid][0] >> qs[qid][1];
        qs[qid][0]--;
        qs[qid][2] = qid;
    }
    sort(qs.begin(), qs.end(), [&](tint a, tint b){return a[1] < b[1];});

    const int MAX = 110000;
    vector<pint> leftist(MAX, pint(-1, -1));

    // l 以上となる最大の v を求めたい！！
    SegmentTree<int> seg(MAX, [&](int a, int b){return max(a, b);}, -1);

    auto push = [&](int val, int id) {
        int before = leftist[val].second;
        if (id > leftist[val].first) {
            leftist[val].second = leftist[val].first;
            leftist[val].first = id;
        } else if (id > leftist[val].second) {
            leftist[val].second = id;
        }
        int after = leftist[val].second;
        seg.set(val, after);
    };

    int rid = 0;
    vector<int> res(Q);
    for (auto [l_, r, qid] : qs) {
        int l = l_;
        while (rid < r) {
            for (ll v = 1; v * v <= A[rid]; v++) {
                if (A[rid] % v == 0) {
                    push(v, rid);
                    if (v != A[rid] / v) push(A[rid] / v, rid);
                }
            }
            rid++;
        }

        auto func = [&](int val) -> bool {return val < l;};
        int vl = seg.min_left(func);
        res[qid] = vl-1;

        //cout << "------" << endl; COUT(l); COUT(r); COUT(qid); COUT(seg); COUT(vl);
    }
    for (auto val : res) cout << val << '\n';
}
accuracy: 1
time_ms: 750
memory_kb: 7008
final_rank: 5

code_snippet: #pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")

#include <bits/stdc++.h>
using namespace std;

template<class S, class T> inline bool chmax(S &a, T b) { return (a < b ? a = b, 1 : 0); }
template<class S, class T> inline bool chmin(S &a, T b) { return (a > b ? a = b, 1 : 0); }

using pint = pair<int, int>;
using pll = pair<long long, long long>;
using tint = array<int, 3>;
using tll = array<long long, 3>;
using fint = array<int, 4>;
using fll = array<long long, 4>;
using vll = vector<long long>;
using ll = long long;
using u32 = unsigned int;
using u64 = unsigned long long;
using int128 = __int128;
using u128 = unsigned __int128;
template <class T>
using min_priority_queue = priority_queue<T, vector<T>, greater<T>>;

#define REP(i, a) for (long long i = 0; i < (long long)(a); i++)
#define REP2(i, a, b) for (long long i = a; i < (long long)(b); i++)
#define RREP(i, a) for (long long i = (a)-1; i >= (long long)(0); --i)
#define RREP2(i, a, b) for (long long i = (b)-1; i >= (long long)(a); --i)
#define EB emplace_back
#define PB push_back
#define MP make_pair
#define MT make_tuple
#define FI first
#define SE second
#define ALL(x) x.begin(), x.end()
#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl

// debug stream
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P)
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, deque<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, vector<vector<T> > P)
{ for (int i = 0; i < P.size(); ++i) { s << endl << P[i]; } return s << endl; }
template<class T> ostream& operator << (ostream &s, set<T> P)
{ for (auto it : P) { s << "<" << it << "> "; } return s; }
template<class T> ostream& operator << (ostream &s, multiset<T> P)
{ for (auto it : P) { s << "<" << it << "> "; } return s; }
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P)
{ for (auto it : P) { s << "<" << it.first << "->" << it.second << "> "; } return s; }



// Segment Tree
template<class Monoid> struct SegmentTree {
    using Func = function<Monoid(Monoid, Monoid)>;

    // core member
    int N;
    Func OP;
    Monoid IDENTITY;
    
    // inner data
    int log, offset;
    vector<Monoid> dat;

    // constructor
    SegmentTree() {}
    SegmentTree(int n, const Func &op, const Monoid &identity) {
        init(n, op, identity);
    }
    SegmentTree(const vector<Monoid> &v, const Func &op, const Monoid &identity) {
        init(v, op, identity);
    }
    void init(int n, const Func &op, const Monoid &identity) {
        N = n;
        OP = op;
        IDENTITY = identity;
        log = 0, offset = 1;
        while (offset < N) ++log, offset <<= 1;
        dat.assign(offset * 2, IDENTITY);
    }
    void init(const vector<Monoid> &v, const Func &op, const Monoid &identity) {
        init((int)v.size(), op, identity);
        build(v);
    }
    void pull(int k) {
        dat[k] = OP(dat[k * 2], dat[k * 2 + 1]);
    }
    void build(const vector<Monoid> &v) {
        assert(N == (int)v.size());
        for (int i = 0; i < N; ++i) dat[i + offset] = v[i];
        for (int k = offset - 1; k > 0; --k) pull(k);
    }
    int size() const {
        return N;
    }
    Monoid operator [] (int i) const {
        return dat[i + offset];
    }
    
    // update A[i], i is 0-indexed, O(log N)
    void set(int i, const Monoid &v) {
        assert(0 <= i && i < N);
        int k = i + offset;
        dat[k] = v;
        while (k >>= 1) pull(k);
    }
    
    // get [l, r), l and r are 0-indexed, O(log N)
    Monoid prod(int l, int r) {
        assert(0 <= l && l <= r && r <= N);
        Monoid val_left = IDENTITY, val_right = IDENTITY;
        l += offset, r += offset;
        for (; l < r; l >>= 1, r >>= 1) {
            if (l & 1) val_left = OP(val_left, dat[l++]);
            if (r & 1) val_right = OP(dat[--r], val_right);
        }
        return OP(val_left, val_right);
    }
    Monoid all_prod() {
        return dat[1];
    }
    
    // get max r that f(get(l, r)) = True (0-indexed), O(log N)
    // f(IDENTITY) need to be True
    int max_right(const function<bool(Monoid)> f, int l = 0) {
        if (l == N) return N;
        l += offset;
        Monoid sum = IDENTITY;
        do {
            while (l % 2 == 0) l >>= 1;
            if (!f(OP(sum, dat[l]))) {
                while (l < offset) {
                    l = l * 2;
                    if (f(OP(sum, dat[l]))) {
                        sum = OP(sum, dat[l]);
                        ++l;
                    }
                }
                return l - offset;
            }
            sum = OP(sum, dat[l]);
            ++l;
        } while ((l & -l) != l);  // stop if l = 2^e
        return N;
    }

    // get min l that f(get(l, r)) = True (0-indexed), O(log N)
    // f(IDENTITY) need to be True
    int min_left(const function<bool(Monoid)> f, int r = -1) {
        if (r == 0) return 0;
        if (r == -1) r = N;
        r += offset;
        Monoid sum = IDENTITY;
        do {
            --r;
            while (r > 1 && (r % 2)) r >>= 1;
            if (!f(OP(dat[r], sum))) {
                while (r < offset) {
                    r = r * 2 + 1;
                    if (f(OP(dat[r], sum))) {
                        sum = OP(dat[r], sum);
                        --r;
                    }
                }
                return r + 1 - offset;
            }
            sum = OP(dat[r], sum);
        } while ((r & -r) != r);
        return 0;
    }
    
    // debug
    friend ostream& operator << (ostream &s, const SegmentTree &seg) {
        for (int i = 0; i < (int)seg.size(); ++i) {
            s << seg[i];
            if (i != (int)seg.size() - 1) s << " ";
        }
        return s;
    }
};


/*/////////////////////////////*/
// Solver
/*/////////////////////////////*/

const int MAX = 110000;
int main() {
    int N, Q;
    cin >> N;
    vector<ll> A(N);
    REP(i, N) cin >> A[i];
    cin >> Q;
    vector<ll> L(Q), R(Q);
    REP(i, Q) cin >> L[i] >> R[i], L[i]--, R[i]--;
    vector<vector<pll>> LR(MAX);
    REP(i, Q) LR[L[i]].EB(R[i], i);
    
    const ll INF = 1LL << 60;
    auto op = [&](ll p, ll q) -> ll { return min(p, q); };
    SegmentTree<ll> seg1(MAX, op, INF), seg2(MAX, op, INF);

    vector<ll> res(Q);
    RREP(l, N) {
        vector<ll> div;
        for (ll a = 1; a*a <= A[l]; a++) {
            if (A[l] % a == 0) {
                div.EB(a);
                if (a * a != A[l]) div.EB(A[l] / a);
            }
        }
        for (auto d : div) {
            if (d >= MAX) continue;
            auto id1 = seg1[d], id2 = seg2[d];
            seg2.set(d, id1);
            seg1.set(d, l);
        }

        // cout << "--------------=" << endl;
        // COUT(l);
        // COUT(seg1);
        // COUT(seg2);

        for (const auto p : LR[l]) {
            // find max v such that seg2.prod(v, MAX) <= r
            // get min l that f(get(l, r)) = True (0-indexed), O(log N)
            // f(IDENTITY) need to be True
            // int min_left(const function<bool(Monoid)> f, int r = -1) {
            auto l = seg2.min_left([&](ll val) -> bool {return val > p.first; });
            res[p.second] = l-1;

            // cout << p << ": " << l-1 << endl;
        }
    }
    for (auto v : res) cout << v << '\n';
}
accuracy: 1
time_ms: 1230
memory_kb: 15884
final_rank: 8

code_snippet: // AOJ #1463
// Greatest of the Greatest Common Divisors 2025.1.14

#include <bits/stdc++.h>
using namespace std;

#define gc() getchar_unlocked()
#define pc(c) putchar_unlocked(c)

int Cin() {  // 整数の入力
	int n = 0, c = gc();
	do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
	return n;
}

void Cout(int n) { // 整数の表示（出力）
	char b[30];
	if (!n) pc('0');
	else {
		if (n < 0) pc('-'), n = -n;
		int i = 0; while (n) b[i++] = n % 10 + '0', n /= 10;
		while (i--) pc(b[i]);
	}
	pc('\n');
}

const int MAXVAL = 100000;

struct BIT {
    int n;
    vector<int> tree;
    BIT(int n) : n(n) {
        tree.assign(n+1, 0);
    }
    void update(int i, int val) {
        for(; i <= n; i += i & -i)
            tree[i] = max(tree[i], val);
    }
    int query(int i) {
        int res = 0;
        for(; i; i -= i & -i)
            res = max(res, tree[i]);
        return res;
    }
};
 
struct Event { int q, p, d; };
 
struct EventComparator {
    bool operator()(const Event &a, const Event &b) const {
        return a.q < b.q;
    }
};
 
struct Query { int l, r, idx; };
 
struct QueryComparator {
    bool operator()(const Query &a, const Query &b) const {
        return a.r < b.r;
    }
};
 
int main(){
    int n = Cin(); 
    vector<int> arr(n+1);
    for (int i = 1; i <= n; i++) arr[i] = Cin();

    vector<vector<int>> divisors(MAXVAL+1);
    for (int d = 1; d <= MAXVAL; d++){
        for (int mult = d; mult <= MAXVAL; mult += d)
            divisors[mult].push_back(d);
    }
 
    vector<vector<int>> posOfDiv(MAXVAL+1);
    for (int i = 1; i <= n; i++){
        int x = arr[i];
        for (int d : divisors[x])
            posOfDiv[d].push_back(i);
    }
 
    vector<Event> events;
    events.reserve(n * 40);
    for (int d = 1; d <= MAXVAL; d++){
        if(posOfDiv[d].size() >= 2){
            for (size_t j = 0; j+1 < posOfDiv[d].size(); j++){
                Event ev;
                ev.p = posOfDiv[d][j];
                ev.q = posOfDiv[d][j+1];
                ev.d = d;
                events.push_back(ev);
            }
        }
    }
    sort(events.begin(), events.end(), EventComparator());
 
    int q = Cin();
    vector<Query> queries(q);
    for (int i = 0; i < q; i++){
        int l = Cin(), r = Cin();
        queries[i] = {l, r, i};
    }
    sort(queries.begin(), queries.end(), QueryComparator());
 
    BIT bit(n);
 
    vector<int> ans(q, 0);
    int evIndex = 0;
    int eventsSize = events.size();
    for(auto &qu : queries){
        while(evIndex < eventsSize && events[evIndex].q <= qu.r) {
            int pos = events[evIndex].p;
            int cand = events[evIndex].d;
            int idxInBIT = n - pos + 1;
            bit.update(idxInBIT, cand);
            evIndex++;
        }
        int best = bit.query(n - qu.l + 1);
        ans[qu.idx] = best;
    }
    for (int i = 0; i < q; i++) Cout(ans[i]);
    return 0;
}
accuracy: 1
time_ms: 750
memory_kb: 256884
final_rank: 14

code_snippet: // AOJ #1463
// Greatest of the Greatest Common Divisors 2025.1.14

#include <bits/stdc++.h>
using namespace std;
const int MAXVAL = 100000;

struct BIT {
    int n;
    vector<int> tree;
    BIT(int n) : n(n) {
        tree.assign(n+1, 0);
    }
    void update(int i, int val) {
        for(; i <= n; i += i & -i)
            tree[i] = max(tree[i], val);
    }
    int query(int i) {
        int res = 0;
        for(; i; i -= i & -i)
            res = max(res, tree[i]);
        return res;
    }
};
 
struct Event { int q, p, d; };
 
struct EventComparator {
    bool operator()(const Event &a, const Event &b) const {
        return a.q < b.q;
    }
};
 
struct Query { int l, r, idx; };
 
struct QueryComparator {
    bool operator()(const Query &a, const Query &b) const {
        return a.r < b.r;
    }
};
 
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
 
    int n; 
    cin >> n;
    vector<int> arr(n+1);
    for (int i = 1; i <= n; i++) cin >> arr[i];

    vector<vector<int>> divisors(MAXVAL+1);
    for (int d = 1; d <= MAXVAL; d++){
        for (int mult = d; mult <= MAXVAL; mult += d)
            divisors[mult].push_back(d);
    }
 
    vector<vector<int>> posOfDiv(MAXVAL+1);
    for (int i = 1; i <= n; i++){
        int x = arr[i];
        for (int d : divisors[x])
            posOfDiv[d].push_back(i);
    }
 
    vector<Event> events;
    events.reserve(n * 40);
    for (int d = 1; d <= MAXVAL; d++){
        if(posOfDiv[d].size() >= 2){
            for (size_t j = 0; j+1 < posOfDiv[d].size(); j++){
                Event ev;
                ev.p = posOfDiv[d][j];
                ev.q = posOfDiv[d][j+1];
                ev.d = d;
                events.push_back(ev);
            }
        }
    }
    sort(events.begin(), events.end(), EventComparator());
 
    int q;
    cin >> q;
    vector<Query> queries(q);
    for (int i = 0; i < q; i++){
        int l, r;
        cin >> l >> r;
        queries[i] = {l, r, i};
    }
    sort(queries.begin(), queries.end(), QueryComparator());
 
    BIT bit(n);
 
    vector<int> ans(q, 0);
    int evIndex = 0;
    int eventsSize = events.size();
    for(auto &qu : queries){
        while(evIndex < eventsSize && events[evIndex].q <= qu.r) {
            int pos = events[evIndex].p;
            int cand = events[evIndex].d;
            int idxInBIT = n - pos + 1;
            bit.update(idxInBIT, cand);
            evIndex++;
        }
        int best = bit.query(n - qu.l + 1);
        ans[qu.idx] = best;
    }
    for (int i = 0; i < q; i++){
        cout << ans[i] << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 770
memory_kb: 258124
final_rank: 15

code_snippet: #include<bits/stdc++.h>
#include<bits/extc++.h>
 
#define F first
#define S second
#define pb push_back
#define pob pop_back
#define pf push_front
#define pof pop_front
#define mp make_pair
#define mt make_tuple
#define all(x) (x).begin(),(x).end()
#define mem(x,i) memset((x),(i),sizeof((x)))
 
using namespace std;
//using namespace __gnu_pbds;
using pii = pair<long long,long long>;
using ld = long double;
using ll = long long;
 
mt19937 mtrd(chrono::steady_clock::now().time_since_epoch().count());
 
const int mod = 1000000007;
const int mod2 = 998244353;
const ld PI = acos(-1);
 
#define Bint __int128
#define int long long

namespace DEBUG{ 
	template <typename T, typename T2>
	ostream& operator<<(ostream& os, const pair<T, T2>& pr) {
		os << "( " << pr.first << ", " << pr.second << ")";
		return os;
	}

	template <typename T>
	inline void printv(T l, T r){
		cerr << "DEBUG: [ ";
		for(; l != r; l++)
			cerr << *l << ", ";
		cerr << "]" << endl;
	}
	
	template <typename T>
	inline void _debug(const char* format, T t) {
		cerr << format << '=' << t << endl;
	}
	
	template <class First, class... Rest>
	inline void _debug(const char* format, First first, Rest... rest) {
		while (*format != ',')
			cerr << *format++;
		cerr << '=' << first << ",";
		_debug(format + 1, rest...);
	}

//	#define TEST
	#ifdef TEST
	#define debug(...) cerr << "DEBUG: ",_debug(#__VA_ARGS__, __VA_ARGS__)
	#else
	#define debug(...) void(0)
	#define printv(...) void(0)
	#endif
}  // namespace DEBUG

using namespace DEBUG;

/* ----------------------------------------  */
const int N = 1e5 + 10;
const int inf = 1e18 + 10;

struct segtree{
	int seg[N << 2];	
	void upd(int l, int r, int p, int v, int idx = 1){
		if(l == r){
			seg[idx] = v;
			return;
		}
		int mid = (l + r) >> 1;
		if(p <= mid)
			upd(l, mid, p, v, idx << 1);
		else
			upd(mid + 1, r, p, v, idx << 1 | 1);
		seg[idx] = max(seg[idx << 1], seg[idx << 1 | 1]);
	}

	int query(int l, int r, int ql, int qr, int idx = 1){
		if(ql == l && qr == r)
			return seg[idx];
		int mid = (l + r) >> 1;
		if(qr <= mid)
			return query(l, mid, ql, qr, idx << 1);
		else if(ql > mid)
			return query(mid + 1, r, ql, qr, idx << 1 | 1);
		return max(query(l, mid, ql, mid, idx << 1), query(mid + 1, r, mid + 1, qr, idx << 1 | 1));
	}

	segtree(){
		for(int i = 0; i < (N << 2); i++)
			seg[i] = -inf;
	}
}sgt;

int n, q;
int a[N];
int ans[N];
int llst[N];

void upd(int idx, int num){
	if(llst[num] != -1)
		sgt.upd(1, N - 1, num, llst[num]), debug(num, idx);	
	llst[num] = idx;
}

void solve(){
	cin >> n;
	for(int i = 0; i < N; i++)
		llst[i] = -1;
	for(int i = 0; i < n; i++)
		cin >> a[i];
	int p = 0;
	cin >> q;
	vector<array<int, 3>>query(q);
	for(auto &[r, l, id] : query){
		cin >> l >> r;
		l--, r--;
		id = p++;
	}
	sort(all(query));
	p = 0;
	for(auto [r, l, id] : query){
		while(p <= r){
			for(int i = 1; i * i <= a[p]; i++){
				if(a[p] % i == 0){
					upd(p, i);	
					if(a[p] / i != i)
						upd(p, a[p] / i);
				}
			}
			p++;
		}
		int L = 1, R = N;
		while(L < R){
			int mid = (L + R + 1) >> 1;
			if(sgt.query(1, N - 1, mid, N - 1) >= l)
				L = mid;
			else
				R = mid - 1;
		}
		ans[id] = R;
	}
	for(int i = 0; i < q; i++)
		cout << ans[i] << '\n';
}
 
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	int t = 1; 
	// cin >> t;
	while(t--)
		solve();
}
accuracy: 1
time_ms: 640
memory_kb: 10984
final_rank: 4

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int ll
#define pii pair<int, int>
#define X first
#define Y second
#define F first
#define S second
#define vi vector<int>
#define SZ(a) ((int)a.size())
#define ALL(v) v.begin(), v.end()
#define pb push_back
#define eb emplace_back
#define push emplace
#define lb(x, v) lower_bound(ALL(x), v)
#define ub(x, v) upper_bound(ALL(x), v)
#define re(x) reverse(ALL(x))
#define uni(x) x.resize(unique(ALL(x)) - x.begin())
#define inf 1000000000
#define INF 1000000000000000000
#define mod 1000000007
#define MOD 998244353
#define get_bit(x, y) ((x>>y)&1)
#define mkp make_pair
#define IO ios_base::sync_with_stdio(0); cin.tie(0);
void abc() {cerr << endl;}
template <typename T, typename ...U> void abc(T a, U ...b) {
    cerr << a << ' ', abc(b...);
}
#ifdef debug
#define test(args...) abc("[" + string(#args) + "]", args)
#else
#define test(args...) void(0)
#endif

template<class T> bool ckmin(T& a, const T& b) { return b<a ? a=b, 1 : 0; }
template<class T> bool ckmax(T& a, const T& b) { return a<b ? a=b, 1 : 0; }

struct Segment_Tree {
#define ls (x<<1)
#define rs ((x<<1)|1)
#define mid ((l+r)>>1)
    int n;
    vector<int> seg;
    Segment_Tree(int _n): n(_n), seg(_n * 4) {}

    inline int op(const int &a, const int &b) {
        return max(a, b);
    }

    void up(int x) {
        seg[x] = op(seg[ls], seg[rs]);
    }

    void modify(int p, int v, int l, int r, int x) {
        if(l == r) {
            seg[x] = max(seg[x], v);
            return;
        }
        if(p <= mid) modify(p, v, l, mid, ls);
        else modify(p, v, mid+1, r, rs);
        up(x);
    }
    void modify(int p, int v) { modify(p, v, 0, n, 1); }

    int query(int a, int b, int l, int r, int x) {
        if(a <= l and r <= b) return seg[x];
        int res = 0;
        if(a <= mid) res = query(a, b, l, mid, ls);
        if(b > mid) res = op(res, query(a, b, mid+1, r, rs));
        return res;
    }
    int query(int a, int b) { return query(a, b, 0, n , 1); }
};

inline void solve() {
  int n; cin >> n;
  vector<int> a(n);
  int mx = 0;
  for (int &i : a) { 
    cin >> i;
    mx = max(i, mx);
  }

  vector<vector<int>> div(100001);

  for (int i = 1; i <= mx; i++) {
    for (int j = i; j <= mx; j += i) {
      div[j].eb(i);
    }
  }
  for (int i = 1; i <= mx; i++) reverse(ALL(div[i]));

  vector<vector<pii>> lst(n);
  map<int, int> mp;
  for (int i = 0; i < n; i++) {
    for (int j : div[a[i]]) {
      if (mp.find(j) != mp.end()) {
        if (lst[i].empty() || lst[i].back().second < mp[j]) {
          lst[i].eb(j, mp[j]);
        }
      }
      mp[j] = i;
    }
  }

  int q; cin >> q;
  vector<vector<pii>> qry(n);
  for (int i = 0; i < q; i++) {
    int l, r;
    cin >> l >> r;
    l--, r--;
    qry[r].eb(l, i);
  }

  Segment_Tree seg(n + 1);
  vector<int> ans(q);
  for (int i = 0; i < n; i++) {
    for (auto [val, pos] : lst[i]) {
      seg.modify(pos, val);
    }
    for (auto [l, idx] : qry[i]) {
      ans[idx] = seg.query(l, i);
    }
  }
  for (int i : ans) cout << i << '\n';
}

signed main() {
	IO;	
	solve();	
}
accuracy: 1
time_ms: 370
memory_kb: 53032
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;

template<class S, S (*op)(S, S), S (*e)()>
struct SegmentTree{
    int n;
    vector<S> data;

    SegmentTree(int sz=0) : n(1) {
        while(n < sz) n *= 2;
        data.resize(2 * n, e());
    }

    SegmentTree(const vector<S> &V) : n(1) {
        int sz = V.size();
        while(n < sz) n *= 2;
        data.resize(2 * n, e());
        for(int i = 0; i < sz; i++) data[i+n] = V[i];
        for(int i = n - 1; i >= 1; i--) data[i] = op(data[i<<1], data[i<<1|1]);
    }

    void set(int i, S x) {
        i += n;
        data[i] = x;
        while(i > 1) {
            i >>= 1;
            data[i] = op(data[i<<1], data[i<<1|1]);
        }
    }

    S prod(int l, int r) {
        l += n; r += n;
        S vl = e(), vr = e();
        while(l < r) {
            if(l & 1) vl = op(vl, data[l++]);
            if(r & 1) vr = op(data[--r], vr);
            l >>= 1; r >>= 1;
        }
        return op(vl, vr);
    }

    S all_prod() { return data[1]; }

    S get(int i) { return data[i + n]; }
};

constexpr int MX = 1e5;
constexpr int INF = 1e9;

using S = int;
S op(S l, S r) { return min(l, r); }
S e() { return INF; }

struct Query {
    int l, r, i;
};

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    
    int N;
    cin >> N;
    vector<int> A(N);
    for(int i = 0; i < N; i++) {
        cin >> A[i];
    }

    int Q;
    cin >> Q;
    vector<Query> query(Q);
    for(int i = 0; i < Q; i++) {
        cin >> query[i].l >> query[i].r;
        query[i].i = i;
        query[i].l--;
    }

    auto cmp = [&](Query a, Query b) -> bool {
        return a.l < b.l;
    };

    sort(query.rbegin(), query.rend(), cmp);

    // the first idx from left
    vector<int> left(MX + 1, INF);
    // the second idx from left
    SegmentTree<S, op, e> seg(MX + 1);

    int qi = 0;
    vector<int> ans(Q, INF);
    for(int i = N; i--;) {
        // add A[i] to seg
        // calc divisor
        for(int j = 1; j * j <= A[i]; j++) {
            if(A[i] % j == 0) {
                seg.set(j, left[j]);
                left[j] = i;
                int nj = A[i] / j;
                if(j != nj) {
                    seg.set(nj, left[nj]);
                    left[nj] = i;
                }
            }
        }

        // query
        while(qi < Q && query[qi].l == i) {
            // binary search
            auto check = [&](int l) -> bool {
                int prod = seg.prod(l, MX + 1);
                return prod < query[qi].r;
            };

            int lb = 1, ub = MX + 1;
            while(ub - lb > 1) {
                int mid = (ub + lb) / 2;
                if(check(mid)) lb = mid;
                else ub = mid;
            }

            ans[query[qi].i] = lb;

            qi++;
        }
    }

    for(int a : ans) {
        cout << a << "\n";
    }

    return 0;
}
accuracy: 1
time_ms: 250
memory_kb: 6784
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;

template<class S, S (*op)(S, S), S (*e)()>
struct SegmentTree{
    int n;
    vector<S> data;

    SegmentTree(int sz=0) : n(1) {
        while(n < sz) n *= 2;
        data.resize(2 * n, e());
    }

    SegmentTree(const vector<S> &V) : n(1) {
        int sz = V.size();
        while(n < sz) n *= 2;
        data.resize(2 * n, e());
        for(int i = 0; i < sz; i++) data[i+n] = V[i];
        for(int i = n - 1; i >= 1; i--) data[i] = op(data[i<<1], data[i<<1|1]);
    }

    void set(int i, S x) {
        i += n;
        data[i] = x;
        while(i > 1) {
            i >>= 1;
            data[i] = op(data[i<<1], data[i<<1|1]);
        }
    }

    S prod(int l, int r) {
        l += n; r += n;
        S vl = e(), vr = e();
        while(l < r) {
            if(l & 1) vl = op(vl, data[l++]);
            if(r & 1) vr = op(data[--r], vr);
            l >>= 1; r >>= 1;
        }
        return op(vl, vr);
    }

    S all_prod() { return data[1]; }

    S get(int i) { return data[i + n]; }
};

constexpr int MX = 1e5;
constexpr int INF = 1e9;

using S = int;
S op(S l, S r) { return min(l, r); }
S e() { return INF; }

struct Query {
    int l, r, i;
};

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    
    int N;
    cin >> N;
    vector<int> A(N);
    for(int i = 0; i < N; i++) {
        cin >> A[i];
    }

    int Q;
    cin >> Q;
    vector<Query> query(Q);
    for(int i = 0; i < Q; i++) {
        cin >> query[i].l >> query[i].r;
        query[i].i = i;
        query[i].l--;
    }

    auto cmp = [&](Query a, Query b) -> bool {
        return a.l < b.l;
    };

    sort(query.rbegin(), query.rend(), cmp);

    // the first idx from left
    vector<int> left(MX + 1, INF);
    // the second idx from left
    SegmentTree<S, op, e> seg(MX + 1);

    int qi = 0;
    vector<int> ans(Q, INF);
    for(int i = N; i--;) {
        // add A[i] to seg
        // calc divisor
        for(int j = 1; j * j <= A[i]; j++) {
            if(A[i] % j == 0) {
                seg.set(j, left[j]);
                left[j] = i;
                int nj = A[i] / j;
                if(j != nj) {
                    seg.set(nj, left[nj]);
                    left[nj] = i;
                }
            }
        }

        // query
        while(qi < Q && query[qi].l == i) {
            // binary search
            auto check = [&](int l) -> bool {
                int prod = seg.prod(l, MX + 1);
                return prod < query[qi].r;
            };

            int lb = 1, ub = MX;
            while(ub - lb > 1) {
                int mid = (ub + lb) / 2;
                if(check(mid)) lb = mid;
                else ub = mid;
            }

            ans[query[qi].i] = lb;

            qi++;
        }
    }

    for(int a : ans) {
        cout << a << "\n";
    }

    return 0;
}
accuracy: 0.1320754716981132
time_ms: 250
memory_kb: 6784
final_rank: 16

code_snippet: #include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>

using namespace std;

template <class T, T op(T, T), T e()>
struct segtree {
    int n, size, lg;
    vector<T> tree;
    segtree(int n_) : segtree(vector<T>(n_, e())) {}
    void update(int i) { tree[i] = op(tree[i * 2], tree[i * 2 + 1]); }
    segtree(vector<T> v) : n(v.size()), lg(0) {
        while ((1 << lg) < n) lg++;
        size = 1 << lg;
        tree = vector<T>(size * 2);
        for (int i = 0; i < n; i++) {
            tree[i + size] = v[i];
        }
        for (int i = size - 1; i >= 1; i--) {
            update(i);
        }
    }

    void set(int i, T x) {
        i += size;
        tree[i] = x;
        while (i > 1) {
            i >>= 1;
            update(i);
        }
    }

    T get(int i) { return tree[i + size]; }

    T prod(int l, int r) {
        l += size;
        r += size;

        T lp = e(), rp = e();
        while (l < r) {
            if (l & 1) lp = op(lp, tree[l++]);
            if (r & 1) rp = op(tree[--r], rp);
            l >>= 1;
            r >>= 1;
        }

        return op(lp, rp);
    }
};

vector<int> osa_k(int n) {
    vector<int> table(n + 1);
    iota(table.begin(), table.end(), 0);
    vector<int> primes;
    for (int i = 2; i <= n; i++) {
        if (table[i] == i) primes.emplace_back(i);
        for (int j : primes) {
            if (i * j > n) break;
            table[i * j] = j;
        }
    }
    return table;
}

vector<int> divisors(int x) {
    vector<int> res;
    for (int i = 1; i * i <= x; i++) {
        if (x % i == 0) {
            res.emplace_back(i);
            if (i * i != x) res.emplace_back(x / i);
        }
    }
    return res;
}

int op(int a, int b) { return max(a, b); }

int e() { return 1; }

int main() {
    cin.tie(0)->sync_with_stdio(0);
    int n;
    cin >> n;
    vector<int> a(n);
    for (auto &e : a) cin >> e;
    int q;
    cin >> q;
    vector<vector<pair<int, int>>> querys(n);
    for (int i = 0; i < q; i++) {
        int l, r;
        cin >> l >> r;
        l--, r--;
        querys[r].emplace_back(l, i);
    }
    vector<vector<int>> idxs(100'001);
    segtree<int, op, e> seg(n);
    vector<int> ans(q);
    for (int i = 0; i < n; i++) {
        auto D = divisors(a[i]);
        for (auto d : D) {
            if (!idxs[d].empty()) {
                auto j = idxs[d].back();
                seg.set(j, max(d, seg.get(j)));
            }
            idxs[d].emplace_back(i);
        }
        for (auto [l, id] : querys[i]) {
            ans[id] = seg.prod(l, i + 1);
        }
    }
    for (auto i : ans) cout << i << '\n';
}
accuracy: 1
time_ms: 450
memory_kb: 69020
final_rank: 7