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 << ' ';
}

浙公网安备 33010602011771号