GCD的预处理
区间GCD的种类数肯定小于LogN(每次增一个数 产生新的GCD必定小于原来GCD的1/2或者不增加)
类似HDU 3333的插入修改离线法
#include <bits/stdc++.h>
#define N 101000
#define FREI freopen("in.txt","r",stdin)
#define FREO freopen("out.txt","w",stdout)
#define Mem(a,b) memset(a,b,sizeof(a))
#define lson root<<1
#define rson root<<1|1
#define Mid int mid=(l+r)>>1
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
typedef pair<int,int> Pair;
int n,m;
int a[N],ans[N],pre[N*10];
vector<Pair> v[N],Q[N];
int sum[N<<2];
void update(int root,int l,int r,int ql,int qr,int val){
if(l>qr||r<ql)
return;
if(l>=ql&&r<=qr){
sum[root]+=val;
return ;
}
Mid;
update(lson,l,mid,ql,qr,val);
update(rson,mid+1,r,ql,qr,val);
sum[root]=sum[lson]+sum[rson];
}
int query(int root,int l,int r,int ql,int qr){
int res=0;
if(l>qr||r<ql)
return 0;
if(l>=ql&&r<=qr){
return sum[root];
}
Mid;
res+=query(lson,l,mid,ql,qr);
res+=query(rson,mid+1,r,ql,qr);
return res;
}
int main() {
#ifndef ONLINE_JUDGE
FREI;
#endif // ONLINE_JUDGE
while(scanf("%d%d",&n,&m)!=EOF){
Mem(pre,0);
Mem(sum,0);
for(int i=1;i<=n;i++) {
scanf("%d",&a[i]);
v[i].clear();
Q[i].clear();
}
for(int i=1;i<=n;i++){
v[i].push_back(make_pair(a[i],i));
int tmp=a[i];
for(int j=0;j<v[i-1].size();j++){
int gcd=_gcd(tmp,v[i-1][j].first);
if(gcd!=tmp){
v[i].push_back(make_pair(gcd,v[i-1][j].second));
tmp=gcd;
}
}
}
for(int i=0;i<m;i++){
int l,r;
scanf("%d%d",&l,&r);
Q[r].push_back(make_pair(l,i));
}
for(int i=1;i<=n;i++){
for(int j=0;j<v[i].size();j++){
int val=v[i][j].first,id=v[i][j].second;
if(!pre[val]){
update(1,1,n,id,id,1);
pre[val]=id;
}
else if(pre[val]&&pre[val]<id){
update(1,1,n,id,id,1);
update(1,1,n,pre[val],pre[val],-1);
pre[val]=id;
}
}
for(int j=0;j<Q[i].size();j++){
int l=Q[i][j].first,r=i,id=Q[i][j].second;
ans[id]=query(1,1,n,l,r);
}
}
for(int i=0;i<m;i++) printf("%d\n",ans[i]);
}
}