Codeforces - Ant colony

题目链接:Codeforces - Ant colony


看区间是所有数字因子的数的个数,其实就是看区间等于区间gcd的数的个数。

我们直接线段树区间维护这个个数即可。

或者维护区间gcd,然后主席树计算区间等于gcd的个数。


AC代码:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include
//#define int long long
using namespace std;
const int N=1e5+10;
int n,a[N],q;
struct node{int cnt,gd;}t[N<<2],c;
inline node merge(node a,node b){
	c.gd=__gcd(a.gd,b.gd);
	c.cnt=(a.gd==c.gd)*a.cnt+(b.gd==c.gd)*b.cnt;
	return c;
}
#define mid (l+r>>1)
void build(int p,int l,int r){
	if(l==r){t[p].gd=a[l],t[p].cnt=1; return ;}
	build(p<<1,l,mid),build(p<<1|1,mid+1,r);
	t[p]=merge(t[p<<1],t[p<<1|1]);
}
node ask(int p,int l,int r,int ql,int qr){
	if(l==ql&&r==qr)	return t[p];
	if(qr<=mid)	return ask(p<<1,l,mid,ql,qr);
	else if(ql>mid)	return ask(p<<1|1,mid+1,r,ql,qr);
	else return merge(ask(p<<1,l,mid,ql,mid),ask(p<<1|1,mid+1,r,mid+1,qr));
}
signed main(){
	cin>>n;
	for(int i=1;i<=n;i++)	scanf("%d",&a[i]);
	cin>>q;	build(1,1,n);
	for(int i=1,l,r;i<=q;i++)	
		scanf("%d %d",&l,&r),printf("%d\n",r-l+1-ask(1,1,n,l,r).cnt);
	return 0;
}

你可能感兴趣的:(线段树,Codeforces)