題目鏈接
http://acm.split.hdu.edu.cn/showproblem.php?pid=5869
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:
for(int i=1;i<=N;i++)
{
int tot=a[i],pos=i;
for(int j=0;j<v[i-1].size();j++)
{
int r=__gcd(a[i],v[i-1][j].first);
if(tot!=r)
{
v[i].push_back(make_pair(tot,pos));
tot=r; pos=v[i-1][j].second;
}
}
v[i].push_back(make_pair(tot,pos));
}
然後對Q次詢問離線處理,先輸入Q次詢問的區間,然後按右端點從小到大排序,i從1~N循環,當i==node[len].r 則 ans[node[len].id]=Sum(i)-Sum(node[len].l-1) ;
可以方便快速的用樹狀數組處理;
代碼如下:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#include <vector>
using namespace std;
int a[100005];
int c[1000005];
int vis[1000005];
int sum[100005];
struct Node
{
int l,r;
int id;
}node[100005];
bool cmp(const Node s1,const Node s2)
{
return s1.r<s2.r;
}
vector<pair<int,int> > v[100005];
int __gcd(int x,int y)
{
int r=x%y;
x=y;
y=r;
if(r==0) return x;
return __gcd(x,y);
}
int Lowbit(int t)
{
return t&(t^(t-1));
}
int Sum(int x)
{
int sum = 0;
while(x > 0)
{
sum += c[x];
x -= Lowbit(x);
}
return sum;
}
void add(int li,int t)
{
while(li<=1000005)
{
c[li]+=t;
li=li+Lowbit(li);
}
}
int main()
{
int N,Q;
while(scanf("%d%d",&N,&Q)!=EOF)
{
for(int i=1;i<=N;i++) scanf("%d",&a[i]);
for(int i=1;i<=N;i++)
{
int tot=a[i],pos=i;
for(int j=0;j<v[i-1].size();j++)
{
int r=__gcd(a[i],v[i-1][j].first);
if(tot!=r)
{
v[i].push_back(make_pair(tot,pos));
tot=r; pos=v[i-1][j].second;
}
}
v[i].push_back(make_pair(tot,pos));
}
for(int i=0;i<Q;i++)
scanf("%d%d",&node[i].l,&node[i].r),node[i].id=i;
sort(node,node+Q,cmp);
memset(c,0,sizeof(c));
memset(vis,0,sizeof(vis));
int len=0;
for(int i=1;i<=N;i++)
{
for(int j=0;j<v[i].size();j++)
{
int s1=v[i][j].first;
int s2=v[i][j].second;
if(vis[s1]){
add(vis[s1],-1);
}
vis[s1]=s2;
add(s2,1);
}
while(node[len].r==i)
{
sum[node[len].id]=Sum(i)-Sum(node[len].l-1);
len++;
}
}
for(int i=0;i<Q;i++)
printf("%d\n",sum[i]);
for(int i=0;i<=N;i++)
v[i].clear();
}
return 0;
}