解题思路:首先这题a[i]值最大1e6所以可以不用考虑离散化,但是为了方便数据扩大我强行再加了一个log(n)复杂度进行数据离散化。所以现在的复杂度应该是nlog(n)*log(n),不离散的话一个log(n)就可以了。
vec[i]数组保存保存区间右界为i的所有gcd情况和该gcd最后出现的位置,那么从i位置一直向左扫gcd肯定是会越来越小的或者不变,变小的话最少变小2倍,所以一个前缀gcd个数不会超过他的log(a[i])的个数。所以我们可以用nlog(n)处理出所有位置做右边界的gcd值和他的最后出现的位置。可以采用a[i]和vec[i-1]里面的数gcd就可以得到vec[i]
离散化:在gcd过大的情况下才使用
离线:将要查询的所有区间以r从小到大排序之后,从小到大考虑。更新vec[i]里面的gcd,如果里面的gcd有出现过,取消掉之前的位置,改换为现在的位置,因为现在的位置肯定包含之前的位置了(以i为右边界那么如果j位置能考虑到,那么j右边的位置也都能取到,所以以取最右边的为准)。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mx = 1e5 + 10;
int n,m,gcd[mx*18],a[mx],top,tot;
vector <pair<int,int>> vec[mx],q[mx];
//每个前缀i的gcd不同个数不会超过log(a[i]),因为gcd肯定最少是以2倍减少的
int sum[mx],last[mx*18],ans[mx];
void add(int x,int v)
{
while(x<=n){
sum[x] += v;
x += x&(-x);
}
}
int get_sum(int x)
{