Long long ago, there was an ancient rabbit kingdom in the forest. Every rabbit in this kingdom was not cute but totally pugnacious, so the kingdom was in chaos in season and out of season.
n rabbits were numbered form 1 to n. All rabbits' weight is an integer. For some unknown reason, two rabbits would fight each other if and only if their weight is NOT co-prime.
Now the king had arranged the n rabbits in a line ordered by their numbers. The king planned to send some rabbits into prison. He wanted to know that, if he sent all rabbits between the i-th one and the j-th one(including the i-th one and the j-th one) into prison, how many rabbits in the prison would not fight with others.
Please note that a rabbit would not fight with himself.
Sample Input
3 2
2 1 4
1 2
1 3
6 4
3 6 1 2 5 3
1 3
4 6
4 4
2 6
0 0
Sample Output
2
1
1
3
1
2
解:
题意:告诉你 a[i]和他不互质的a[i]打架 问区间多少个不打架?
可以想到要用树状数组离线,
1、然后凑出询问形式,问 l,r区间内 有多少点i 满足 L[i]>=l or R[i]<=r
2、因为两个是或的关系 考虑容痴求解
3、那么拆分成三次询问,一次询问的两个条件或的满足个数为: 两个条件分别满足之和-两条件同时满足之和
类似于 P(A+B) =P(A)+P(B)-P(AB)
区间内求区间的方法是和 之前有某提求一个树子树独有的颜色个数个数类似
1.对询问的r排序(升)2.对每个区间的r同样升序3.更新4.查询
void run(int x){
mem(c,0);
for(int i=1,j=1;i<=m;i++){
while(seg[x][j].r<=que[i].r and j<=n){
add(seg[x][j].l,1);
j+=1;
}
ans[x][que[i].ind]=ask(que[i].r)-ask(que[i].l-1);
}
}
AC代码:
预处理初始的L[i]和R[i]的 pos数组会呗卡常 ,pos要改成一维
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <vector>
#define ll long long
using namespace std;
const int maxn =2e5+10;
int rd() {int t;scanf("%d",&t);return t;}
#define en '\n'
#define mem(a,b) memset(a,b,sizeof(a))
#define pb push_back
//#define int register int
int a[maxn],n,m,pos[maxn],L[maxn],R[maxn],c[maxn],que_tot,len[maxn],mx;
void build_seg(){
for(int j=0;j<=mx;j++)pos[j]=0;
for(int i=1;i<=n;i++){
int x=a[i];
for(int j=2;j*j<=x ;j++){
if(x%j==0){
L[i]=max(L[i],pos[j]);
pos[j]=i;
while((x%j)==0)x/=j;
}
}
if(x!=1){
L[i]=max(pos[x],L[i]);
pos[x]=i;
}
}
for(int j=0;j<=mx;j++){
pos[j]=n+1;
}
for(int i=n;i>=1;--i){
int x=a[i];
for(int j=2;j*j<=x ;j++){
if(x%j==0){
R[i]=min(R[i],pos[j]);
pos[j]=i;
while((x%j)==0)x/=j;
}
}
if(x>1){
R[i]=min(pos[x],R[i]);
pos[x]=i;
}
}
}
struct node{
int l,r,ind;
}que[maxn],seg[3][maxn];
bool cmp(node a,node b){return a.r<b.r;}
int ans[3][maxn];
void place_seg(){
for(int i=1;i<=n;i++){
seg[0][i]=(node){L[i],i,0};
}
for(int i=1;i<=n;i++){
seg[1][i]=(node){i,R[i],0};
}
for(int i=1;i<=n;i++){
seg[2][i]=(node){L[i],R[i],0};
}
for(int k=0;k<3;k++){
sort(seg[k]+1,seg[k]+1+n,cmp);
}
}
#define mem(a,b) memset(a,b,sizeof(a))
#define lowbit(x) (x&(-x))
void add(int x,int val){
if(x<=0)return ;
for(;x<maxn-3;x+=lowbit(x)){
c[x]+=val;
}
}
signed ask(int x){if(x<=0)return 0;int res=0;for(;x;x-=lowbit(x))res+=c[x];return res;}
void run(int x){
mem(c,0);
for(int i=1,j=1;i<=m;i++){
while(seg[x][j].r<=que[i].r and j<=n){
add(seg[x][j].l,1);
j+=1;
}
ans[x][que[i].ind]=ask(que[i].r)-ask(que[i].l-1);
}
}
signed main() {
#ifdef swt
freopen("input2.txt","r",stdin);
#endif // local
#define int register int
while(scanf("%d%d",&n,&m)!=EOF and n+m){
mx=0;
for(int i=1;i<=n;i++)a[i]=rd(),L[i]=0,R[i]=n+1,mx=max(mx,a[i]);
build_seg();
for(int i=1;i<=m;i++){
que[i].l=rd();que[i].r=rd();
que[i].ind=i;len[i]=que[i].r-que[i].l+1;
}
sort(que+1,que+1+m,cmp);
place_seg();
for(int k=0;k<3;k++){run(k);}
for(int i=1;i<=m;i++)
{
cout<<len[i]-(ans[0][i]+ans[1][i]-ans[2][i])<<en;
}
}
return 0;
}