Codeforces Round #271 (Div. 2) F - Ant colony 线段树 + GCD
2015-10-08 21:16
260 查看
Codeforces Round #271 (Div. 2) F - Ant colony
每次提问求 给定区间中有多少个数 不能整除区间中其他的数 至少有一次.
其实这个数就是区间的gcd 于是我们只要在求出区间中这个数的个数即可.
对于后者 学习到一个新方法 记录每次出现位置二分找.
题意:
给定一个序列 有M个提问每次提问求 给定区间中有多少个数 不能整除区间中其他的数 至少有一次.
思路:
题意转化一下就是求区间中有多少个数能整除其他数.其实这个数就是区间的gcd 于是我们只要在求出区间中这个数的个数即可.
对于后者 学习到一个新方法 记录每次出现位置二分找.
#include <bits/stdc++.h> #define lson num<<1 #define rson num<<1|1 #define gl l,m,lson #define gr m+1,r,rson #define PARA int l=1,int r=n,int num=1 using namespace std; const int MAXN = 1e5+100; int n; int gcd(int a,int b) { if(b==0) return a; else return gcd(b,a%b); } int a[MAXN]; struct Node { int st[MAXN<<2]; void pushUp(int num) { st[num]=gcd(st[lson],st[rson]); } void init(PARA) { int m=l+r>>1; if(l!=r) init(gl),init(gr),pushUp(num); else st[num]=a[l]; } int query(int a,int b,PARA) { if(a<=l&&r<=b) return st[num]; else { int m=l+r>>1; if(b<=m) return query(a,b,gl); else if(a>m) return query(a,b,gr); else return gcd(query(a,b,gl),query(a,b,gr)); } } }soul; struct myPair { int a,b; void init(int _a,int _b) { a=_a; b=_b; } bool operator<(myPair o) const { return a==o.a?b<o.b:a<o.a; } }pr[MAXN],prt; template <class T> inline void scan_d(T &ret) { char c; ret=0; while((c=getchar())<'0'||c>'9'); while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar(); } int main() { scan_d(n); for(int i=1;i<=n;i++) scan_d(a[i]),pr[i].init(a[i],i); sort(pr+1,pr+1+n); soul.init(); int m,l,r,rl,rr,v; scan_d(m); while(m--) { scan_d(l); scan_d(r); v=soul.query(l,r); prt.init(v,l); rl=lower_bound(pr+1,pr+1+n,prt)-(pr+1); prt.init(v,r+1); rr=lower_bound(pr+1,pr+1+n,prt)-(pr+1); printf("%d\n",r-l+1-(rr-rl)); } return 0; }
相关文章推荐