Codeforces Round #271 (Div. 二) F题 Ant colony(线段树求区间gcd)
Codeforces Round #271 (Div. 2) F题 Ant colony(线段树求区间gcd)
题意:已给数列,给定一个区间,求区间内的某个数x可以整除区间内所有值,求此x的个数
显然个数就是区间内gcd(al,al+1,al+2,...,ar-1,ar)的个数
求任何区间的gcd,可以用线段树解决
求任何区间内某个数的个数可以:先用pair记录值和index,再排序用二分确定上下界,单次复杂度是Ologn
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; #define root 1,n,1 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const int N = 1e5+100; typedef pair<int,int >pii; int d[N<<2]; int a[N]; pii b[N]; int gcd(int a,int b) { if(b==0) return a; else return gcd(b,a%b); } void pushup(int rt) { d[rt]=gcd(d[rt<<1],d[rt<<1|1]); } void build(int l,int r,int rt) { if(l==r) {d[rt]=a[l];return;} int m=(l+r)>>1; build(lson); build(rson); pushup(rt); } int query(int L,int R,int l,int r,int rt) { if(L<=l&&r<=R) return d[rt]; int m=(l+r)>>1; int x,y; x=y=0; if(L<=m) x=query(L,R,lson); if(R>m) y=query(L,R,rson); return gcd(x,y); } int main() { int n,t; cin>>n; for(int i=1;i<=n;i++) cin>>a[i],b[i].first=a[i],b[i].second=i; build(root); sort(b+1,b+1+n); cin>>t; for(int i=1;i<=t;i++) { int l,r; scanf("%d%d",&l,&r); int gd=query(l,r,root); int fr=lower_bound(b+1,b+n+1,pii(gd,l))-(b+1); int ba=lower_bound(b+1,b+1+n,pii(gd,r+1))-(b+1); printf("%d\n",(r-l+1)-(ba-fr)); } }