cf359 D. Pair of Numbers

题意:

找区间最小值等于区间gcd的所有最长区间

\(n\le 3e5\)

思路:

找每个位置 \(i\) 能延伸到的最左位置 \(l_i\)。如果 \(a_i\) 整除 \(a_{l_i-1}\),那么 \(l(i)=l(l_i-1)\)\(r_i\) 同理。

这个过程是线性的。

如果想不到这个,也可以ST表找区间最小值和区间gcd,二分长度线性判断。

const signed N = 3e5 + 3;
int n, a[N], l[N], r[N];

signed main() {
    iofast;
    cin >> n;
    for(int i = 1; i <= n; i++) cin >> a[i];

    for(int i = 1; i <= n; i++) { //算L
        l[i] = i;
        while(l[i] > 1 && a[l[i]-1] % a[i] == 0)
            l[i] = l[l[i]-1];
    }
    for(int i = n; i >= 1; i--) { //算r
        r[i] = i;
        while(r[i] < n && a[r[i]+1] % a[i] == 0)
            r[i] = r[r[i]+1];
    }

    int len = 0; vector<int> ans; //找答案,这题的长度定义为r-l
    for(int i = 1; i <= n; i++) len = max(len, r[i] - l[i]);
    for(int i = 1; i <= n; i++)
        if(r[i] - l[i] == len) ans.pb(l[i]);
    ans.erase(unique(all(ans)), ans.end()); //去重
    cout << ans.size() << ' ' << len << endl;
    for(int i : ans) cout << i << ' ';
}

posted @ 2022-04-01 23:39  Bellala  阅读(29)  评论(0)    收藏  举报