题意:给出一个序列,m次询问,每次询问某个闭区间内所有的子区间组成的不同GCD有多少个
对于一个长度为n的序列来说,组成的不同GCD值不会超过n*logn个,所对应的区间也是如此,预处理出每个下标对应的所有不同gcd区间,右端点排序,对询问离线处理,右端点排序,通过树状数组计数不同的gcd值得到答案
#include<cstring>
#include<string>
#include<iostream>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<map>
#include<cstdlib>
#include<cmath>
#include<vector>
//#pragma comment(linker, "/STACK:1024000000,1024000000");
using namespace std;
#define INF 0x3f3f3f3f
#define maxn 2000004
struct node
{
int l,r;
int g;
node() {}
node(int _l,int _r,int _g)
{
l=_l;
r=_r;
g=_g;
}
friend bool operator < (node A,node B)
{
if(A.r==B.r) return A.l<B.l;
return A.r<B.r;
}
} que[2*maxn];
int n,q;
int a[maxn];
int len;
int dp[maxn][30];
int mm[maxn];
void initRMQ(int n,int b[])
{
mm[0] = -1;
for(int i = 1; i <= n; i++)
{
mm[i] = ((i&(i-1)) == 0)?mm[i-1]+1:mm[i-1];
dp[i][0] = b[i];
}
for(int j = 1; j <= mm[n]; j++)
for(int i = 1; i + (1<<j) -1 <= n; i++)
dp[i][j] = __gcd(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}
int rmq(int x,int y)
{
int k = mm[y-x+1];
return __gcd(dp[x][k],dp[y-(1<<k)+1][k]);
}
void F(int k)
{
int la=k;
int now=a[k];
que[len++]=node(k,k,now);
while(now!=rmq(k,n))
{
int l=la+1,r=n;
while(l+1<=r)
{
int mid=l+r>>1;
if(rmq(k,mid)==now) l=mid+1;
else r=mid-1;
}
for(int i=max(la,l-5); i<=min(n,l+5); i++)
{
if(rmq(k,i)!=now)
{
now=rmq(k,i);
la=i;
que[len++]=node(k,i,now);
break;
}
}
}
}
int c[maxn];
int lowbit(int x)
{
return x&-x;
}
int query(int x)
{
if(x==0) return 0;
int sum=0;
for(; x>0; x-=lowbit(x)) sum+=c[x];
return sum;
}
void update(int x,int val)
{
for(; x<=len; x+=lowbit(x)) c[x]+=val;
}
int ans[maxn];
struct quer
{
int l,r;
int id;
friend bool operator <(quer a,quer b)
{
if(a.r==b.r) return a.l<b.l;
return a.r<b.r;
}
} qe[maxn];
map<int,int>mp;
int main()
{
while(scanf("%d%d",&n,&q)!=EOF)
{
len=1;
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
}
initRMQ(n,a);
for(int i=1; i<=n; i++)
{
F(i);
}
sort(que+1,que+len);
for(int i=0; i<q; i++)
{
scanf("%d%d",&qe[i].l,&qe[i].r);
qe[i].id=i;
}
sort(qe,qe+q);
int num=0;
mp.clear();
int r=1;
memset(c,0,sizeof c);
for(int i=0; i<q; i++)
{
while(r<len&&que[r].r<=qe[i].r)
{
if(que[r].l>mp[que[r].g])
{
if(mp[que[r].g])
{
update(mp[que[r].g],-1);
}
mp[que[r].g]=que[r].l;
update(que[r].l,1);
}
r++;
}
ans[qe[i].id]=query(qe[i].r)-query(qe[i].l-1);
}
for(int i=0; i<q; i++)
{
printf("%d\n",ans[i]);
}
}
return 0;
}
/*
10 10
5 5 4 4 3 2 1 5 10 10
1 2
2 3
3 4
1 10
5 7
2 9
1 9
6 7
8 10
7 10
*/