|   1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
 | //   __________________
//  | ________________ |
//  ||          ____  ||
//  ||   /\    |      ||
//  ||  /__\   |      ||
//  || /    \  |____  ||
//  ||________________||
//  |__________________|
//  \###################\
//   \###################\
//    \        ____       \
//     \_______\___\_______\
// An AC a day keeps the doctor away.
#pragma g++ optimize("Ofast")
#pragma loop_opt(on)
#include <bits/extc++.h>
#ifdef local
#define debug(x) (cerr<<#x<<" = "<<(x)<<'\n')
#else
#define debug(x) ((void)0)
#endif // local
using namespace std;
typedef int64_t ll;
constexpr ll N = 100025, INF = 1e18, MOD = 1000000007, K = 256, inf = 1e9;
ll modpow(ll e,ll p,ll m=MOD) {
    ll r=1;
    while(p) (p&1)&&(r=r*e%m), e=e*e%m, p>>=1;
    return r;
}
template<typename T>
struct SuffixArray {
    int sa[N],rk[N],tmp[N],lcp[N];
    void init(T v[],int n) {
        for(int i = 0; i < n; i++) rk[i] = v[i];
        iota(sa,sa+n,0);
        for(int L = 1; L < n; L*=2) {
            auto cmp = [&](int a,int b) {
                if(rk[a]!=rk[b]) return rk[a]<rk[b];
                int ra = (a+L<n ? rk[a+L] : -1);
                int rb = (b+L<n ? rk[b+L] : -1);
                return ra<rb;
            };
            sort(sa,sa+n,cmp);
            tmp[sa[0]] = 0;
            for(int i = 1; i < n; i++)
                tmp[sa[i]] = tmp[sa[i-1]] + cmp(sa[i-1],sa[i]);
            for(int i = 0; i < n; i++) rk[i] = tmp[i];
        }
        /*
        for(int i = 0; i < n; i++) {
            for(int j = sa[i]; j < n; j++) cout << v[j] << ' ';
            cout << '\n';
        }
        */
        lcp[n-1] = inf;
        for(int i = 0, h = 0; i < n; i++) {
            if(!rk[i]) continue;
            if(h > 0) --h;
            int j = sa[rk[i]-1];
            while(i+h<n && j+h<n && v[i+h]==v[j+h]) ++h;
            lcp[rk[i]-1] = h;
        }
        //for(int i = 0; i < n; i++) cout << lcp[i] << ' ';
    }
};
SuffixArray<int> SA;
struct SegmentTree {
    int mn[N<<1],n;
    void init(int v[],int _n) {
        n = _n;
        for(int i = 0; i < n; i++) mn[i+n] = v[i];
        for(int i = n-1; i > 0; i--) mn[i] = min(mn[i<<1], mn[i<<1|1]);
    }
    int query(int l,int r) {
        //cout << "qry: ";
        //for(int i = l; i < r; i++) cout << mn[i+n] << ' '; cout << '\n';
        int res = inf;
        for(l+=n,r+=n; l<r; l>>=1,r>>=1) {
            if(l&1) res = min(res, mn[l++]);
            if(r&1) res = min(res, mn[--r]);
        }
        return res;
    }
} RMQ;
int n,q,v[N];
signed main() {
    ios_base::sync_with_stdio(0), cin.tie(0);
    cin >> n >> q;
    for(int i = 0; i < n; i++) cin >> v[i];
    for(int i = 0; i < n; i++) v[i] = modpow(v[i], (MOD-1)/2);
    SA.init(v,n);
    RMQ.init(SA.lcp,n);
    for(int i = 0,a,b; i < q; i++) {
        cin >> a >> b;
        if(a == b) cout << n-a << '\n';
        else {
            int l = SA.rk[a], r = SA.rk[b];
            if(l > r) swap(l,r);
            cout << RMQ.query(l,r) << '\n';
        }
    }
}
 |