线段树求GCD
我除了我被吓蒙了还能说啥
先帮我看一眼这两份gcd有什么区别
int gcd(int a,int b)
{
if (a%b==0) return b;
else return gcd(b,a%b)
}
int gcd(int a,int b)
{
if (!b) return a;
else return gcd(b,a%b)
}
一份AC一份RE
我们线段树维护区间GCD然后用一个pair记录数字的位置以及本身,之后查到区间GCD后,在pair里二分一下就好了
代码
//By AcerMo
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int M=1e5+10;
struct Seg
{
int bo[2],so[2],g;
}t[M<<4];
int num[M],tot=0;
int n,cnt=1,rt,m;
typedef pair<int, int> pii;
pii ans[M];
inline int read()
{
int x=0;char ch=getchar();
while (ch>'9'||ch<'0') ch=getchar();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
inline int gcd(int a,int b)
{
if (!b) return a;
return gcd(b,a%b);
}
inline void pushup(int x)
{
int ls=t[x].so[0];
int rs=t[x].so[1];
t[x].bo[0]=t[ls].bo[0];
t[x].bo[1]=t[rs].bo[1];
t[x].g=gcd(t[ls].g,t[rs].g);
return ;
}
inline void built(int l,int r,int x)
{
if (l==r)
{
scanf("%d",&ans[++tot].first);
ans[tot].second=tot;
t[x].bo[0]=t[x].bo[1]=l;
t[x].so[0]=t[x].so[1]=-1;
return (void)(t[x].g=ans[tot].first);
}
int mid=(l+r)>>1;
t[x].so[0]=++cnt;t[x].so[1]=++cnt;
built(l,mid,t[x].so[0]);built(mid+1,r,t[x].so[1]);
pushup(x);
return ;
}
inline int query(int l,int r,int x)
{
if (l<=t[x].bo[0]&&t[x].bo[1]<=r) return t[x].g;
int mid=(t[x].bo[0]+t[x].bo[1])>>1;int a1=0,a2=0;
if (l<=mid) a1=query(l,r,t[x].so[0]);
if (r>mid) a2=query(l,r,t[x].so[1]);
return gcd(a1,a2);
}
int main()
{
n=read();
built(1,n,rt);int l,r;
m=read();
sort(ans+1,ans+n+1);
for (int i=1;i<=m;i++)
{
l=read();r=read();int G=query(l,r,rt);
int a=lower_bound(ans+1,ans+n+1,pii(G,l))-(ans+1);
int b=lower_bound(ans+1,ans+n+1,pii(G,r+1))-(ans+1);
cout<<(r-l+1)-(b-a)<<endl;
}
return 0;
}