区间重复不会影响GCD,ST表当然是支持的啦,常数这么小。
学到了三个东西:
1.lower_bound返回的是大于等于的位置,要判是否不存在(end())和是否超出所求[x,y]范围。
2.ST表更新时存在一个i+(1<<j-1)的下标,存在极大越界隐患,以前数组开的大就无所谓,讲道理边界是要判的。
3.及时存代码,又蓝屏了qwq
#include<iostream> #include<cstdio> #include<vector> #include<map> using namespace std; inline int rd(){ int ret=0,f=1;char c; while(c=getchar(),!isdigit(c))f=c=='-'?-1:1; while(isdigit(c))ret=ret*10+c-'0',c=getchar(); return ret*f; } int LOG2 (unsigned int x) { static const int log_2[256] = { 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 }; int l = -1; while (x >= 256) { l += 8; x >>= 8; } return l + log_2[x]; } const int MAXN=100005; int n,m; int a[MAXN]; int f[MAXN][32]; int id; map<int,int> M; vector<int> V[MAXN]; int gcd(int x,int y){return y?gcd(y,x%y):x;} int query(int x,int y){ if(x==y) return f[x][0]; int len=LOG2(y-x+1); return gcd(f[x][len],f[y-(1<<len)+1][len]); } int main(){ n=rd(); for(int i=1;i<=n;i++) f[i][0]=a[i]=rd(); for(int i=1;i<=n;i++){ if(!M.count(a[i])) M[a[i]]=++id; V[M[a[i]]].push_back(i); } for(int j=1;(1<<j)<=n;j++) for(int i=1;i+(1<<(j-1))<=n;i++) f[i][j]=gcd(f[i][j-1],f[i+(1<<(j-1))][j-1]); m=rd(); int x,y,g,tmp,l,r,ans; for(int i=1;i<=m;i++){ x=rd();y=rd(); g=query(x,y); tmp=M[g]; r=lower_bound(V[tmp].begin(),V[tmp].end(),y)-V[tmp].begin(); l=lower_bound(V[tmp].begin(),V[tmp].end(),x)-V[tmp].begin(); if(r+V[tmp].begin()==V[tmp].end()||V[tmp][r]>y) r--; cout<<y-x+1-(r-l+1)<<endl; } return 0; }