线段树维护区间gcd,查询区间等于gcd的数的个数,有点技巧,用pair记录gcd与num。
#include<bits/stdc++.h>
#define lowbit(x) ((x)&(-(x)))
#define ll long long
#define INF 2147483647
#define CLR(a) memset(a, 0, sizeof(a))
using namespace std;
#define ls (rt<<1)
#define rs (rt<<1|1)
#define MID(a,b) (a+((b-a)>>1))
const int maxn=1e5+10;
int n,m,a[maxn];
typedef pair<int,int> pii;
struct node{
int l,r;
int mid(){return MID(l,r);}
int gcd,num;
};
struct Segtree{
node tree[maxn<<2];
void push_up(int rt){
int a=tree[ls].gcd;
int b=tree[rs].gcd;
int x=tree[ls].num;
int y=tree[rs].num;
int d=__gcd(a,b);
tree[rt].gcd=d;
tree[rt].num=0;
if(d==a) tree[rt].num+=x;
if(d==b) tree[rt].num+=y;
}
void build(int l,int r,int rt){
tree[rt].l=l;tree[rt].r=r;
if(l==r){
tree[rt].gcd=a[l];
tree[rt].num=1;
}
else{
int mid=tree[rt].mid();
build(l,mid,ls);
build(mid+1,r,rs);
push_up(rt);
}
}
pii query(int st,int ed,int rt){
int l=tree[rt].l,r=tree[rt].r;
if(st<=l&&r<=ed) return make_pair(tree[rt].gcd,tree[rt].num);
else{
int mid=tree[rt].mid();
pii p1,p2,p3;
if(st<=mid) p1=query(st,ed,ls);
if(ed>mid) p2=query(st,ed,rs);
int d=__gcd(p1.first,p2.first);
if(d==p1.first) p3.second+=p1.second;
if(d==p2.first) p3.second+=p2.second;
p3.first=d;
return p3;
}
}
}seg;
int main() {
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
seg.build(1,n,1);
scanf("%d",&m);
for(int i=1;i<=m;i++){
int st,ed;
scanf("%d%d",&st,&ed);
printf("%d\n",ed-st+1-seg.query(st,ed,1).second);
}
return 0;
}