Problem Description
This is a simple problem. The teacher gives Bob a list of problems about GCD (Greatest Common Divisor). After studying some of them, Bob thinks that GCD is so interesting. One day, he comes up with a new problem about GCD. Easy as it looks, Bob cannot figure it out himself. Now he turns to you for help, and here is the problem:
Given an array a of N positive integers a1,a2,⋯aN−1,aN ; a subarray of a is defined as a continuous interval between a1 and aN . In other words, ai,ai+1,⋯,aj−1,aj is a subarray of a , for 1≤i≤j≤N . For a query in the form (L,R) , tell the number of different GCDs contributed by all subarrays of the interval [L,R] .
Given an array a of N positive integers a1,a2,⋯aN−1,aN ; a subarray of a is defined as a continuous interval between a1 and aN . In other words, ai,ai+1,⋯,aj−1,aj is a subarray of a , for 1≤i≤j≤N . For a query in the form (L,R) , tell the number of different GCDs contributed by all subarrays of the interval [L,R] .
Input
There are several tests, process till the end of input.
For each test, the first line consists of two integers N and Q , denoting the length of the array and the number of queries, respectively. N positive integers are listed in the second line, followed by Q lines each containing two integers L,R for a query.
You can assume that
1≤N,Q≤100000
1≤ai≤1000000
For each test, the first line consists of two integers N and Q , denoting the length of the array and the number of queries, respectively. N positive integers are listed in the second line, followed by Q lines each containing two integers L,R for a query.
You can assume that
1≤N,Q≤100000
1≤ai≤1000000
Output
For each query, output the answer in one line.
Sample Input
5 3 1 3 4 6 9 3 5 2 5 1 5
Sample Output
6 6 6
调了蛮久的。。码力太差了
某个数结尾,不同的GCD段一共只有log段
这样我们可以离线处理询问。按照右端点排序。
扫描的时候记录这个点往左的各个不同gcd出现的最后位置。用树状数组维护区间和
然后直接统计答案即可
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int tr[1000001];
int fx[1000001];
int a[100001];
inline int gcd(int x,int y)
{
// printf("%d %d\n",x,y);
int m=x%y;
while(m!=0)
{
x=y;
y=m;
m=x%y;
}
return y;
}
inline int lowbit(int x)
{
return x&(-x);
}
inline void inc(int d,int x)
{
if(d==0)
return ;
int i;
for(i=d;i<=1000000;i+=lowbit(i))
tr[i]+=x;
}
inline int sum(int d)
{
int i,ans=0;
for(i=d;i>=1;i-=lowbit(i))
ans+=tr[i];
return ans;
}
struct question
{
int l,r,p;
bool operator <(question y) const
{
return r<y.r;
}
}ask[100001];
int ans[100001];
int qt[1000001],qq[1000001];
bool v[1000001];
set<int> qx;
int main()
{
int n,q;
while(scanf("%d%d",&n,&q)!=EOF)
{
memset(tr,0,sizeof(tr));
memset(fx,0,sizeof(fx));
int i,j;
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
for(i=1;i<=q;i++)
{
scanf("%d%d",&ask[i].l,&ask[i].r);
ask[i].p=i;
}
sort(ask+1,ask+1+q);
int d=1;
int s=0;
int la=0;
memset(v,false,sizeof(v));
for(i=1;i<=n;i++)
{
// printf("%d\n",i);
s=0;
int r=0;
for(j=1;j<=la;j++)
{
int xt=gcd(qq[j],a[i]);
if(fx[xt]==0)
{
r++;
qt[r]=xt;
fx[xt]=fx[qq[j]];
inc(fx[xt],1);
v[xt]=true;
}
else if(!v[xt])
{
r++;
qt[r]=xt;
inc(fx[xt],-1);
fx[xt]=fx[qq[j]];
inc(fx[xt],1);
v[xt]=true;
}
else if(v[xt]&&fx[qq[j]]>fx[xt])
{
inc(fx[xt],-1);
fx[xt]=fx[qq[j]];
inc(fx[xt],1);
}
}
bool flag=false;
if(fx[a[i]]==0)
{
r++;
qt[r]=a[i];
fx[a[i]]=i;
inc(fx[a[i]],1);
}
else if(fx[a[i]]!=i)
{
r++;
qt[r]=a[i];
inc(fx[a[i]],-1);
fx[a[i]]=i;
inc(fx[a[i]],1);
}
while(ask[d].r==i)
{
if(ask[d].l!=ask[d].r)
ans[ask[d].p]=sum(i)-sum(ask[d].l-1);
else
ans[ask[d].p]=1;
d++;
}
la=r;
for(j=1;j<=r;j++)
{
qq[j]=qt[j];
v[qt[j]]=false;
}
}
for(i=1;i<=q;i++)
printf("%d\n",ans[i]);
}
return 0;
}