Codeforces Round #271 (Div. 2)F. Ant colony(线段树)
2014-10-09 21:24
387 查看
题意:给定一个序列,查询t个区间,询问有几个数可以整除其他的数。
一个数可以整除其他的数,那么它必定是这个数的因子之一,一个数可以整除其他数,那么它必定是这些数的公因子,加上他自己的话,他就是这些数的最大公约数,一个区间内的最大公约数肯定是这个区间的最小值,因为比他大的数肯定不能整除他。所以题目是找一个区间所包含的最大公约数的个数。
区间的最大公约数等于,两个子区间分别的最大公约数的最大公约数(好拗口= =)
区间的最小值由两个子区间的最小值决定。
区间最小值的个数由左右区间的最小值决定。
有了上面这三条,就可以用线段树来维护了。
一个数可以整除其他的数,那么它必定是这个数的因子之一,一个数可以整除其他数,那么它必定是这些数的公因子,加上他自己的话,他就是这些数的最大公约数,一个区间内的最大公约数肯定是这个区间的最小值,因为比他大的数肯定不能整除他。所以题目是找一个区间所包含的最大公约数的个数。
区间的最大公约数等于,两个子区间分别的最大公约数的最大公约数(好拗口= =)
区间的最小值由两个子区间的最小值决定。
区间最小值的个数由左右区间的最小值决定。
有了上面这三条,就可以用线段树来维护了。
#include<iostream> #include<algorithm> using namespace std; #define INF 1000000001 #define MAXN 100010 #define MIN(a,b) a<b?a:b #define lson 2*o,l,m #define rson 2*o+1,m+1,r struct Node { int gcd,min,cnt; }tree[4*MAXN],ans; int s[MAXN]; int n; int Gcd(int a,int b){ if(!b)return a; return Gcd(b,a%b); } void init_tree(int o,int l,int r){ if(l==r) { tree[o].min=INF; tree[o].cnt=0; tree[o].gcd=-1; return; } int m=(l+r)>>1; init_tree(lson); init_tree(rson); tree[o].gcd=1; tree[o].cnt=0; tree[o].min=INF; } void insert(int o,int l,int r,int pos,int data) { if(l>pos||r<pos)return; if(l==r&&l==pos){ tree[o].cnt=1; tree[o].min=data; tree[o].gcd=data; return; } int m=(l+r)>>1; insert(lson,pos,data); insert(rson,pos,data); int lg=tree[2*o].gcd,rg=tree[2*o+1].gcd; int lmin=tree[2*o].min,rmin=tree[2*o+1].min; tree[o].min=MIN(lmin,rmin); if(lg!=-1&&rg!=-1) tree[o].gcd=Gcd(tree[2*o].gcd,tree[2*o+1].gcd); else if(lg!=-1) tree[o].gcd=lg; else if(rg!=-1) tree[o].gcd=rg; if(lmin==rmin) tree[o].cnt=tree[2*o].cnt+tree[2*o+1].cnt; else if(lmin<rmin) tree[o].cnt=tree[2*o].cnt; else tree[o].cnt=tree[2*o+1].cnt; } void query(int o,int l,int r,int i,int j) { if(i>r||j<l)return; if(i<=l&&j>=r) { if(ans.gcd==-1)ans.gcd=tree[o].gcd; else ans.gcd=Gcd(ans.gcd,tree[o].gcd); if(ans.min>tree[o].min){ ans.min=tree[o].min; ans.cnt=tree[o].cnt; } else if(ans.min==tree[o].min){ ans.cnt+=tree[o].cnt; } return ; } int m=(l+r)>>1; query(lson,i,j); query(rson,i,j); } int main() { cin>>n; init_tree(1,1,n); for(int i=1;i<=n;i++) { cin>>s[i]; insert(1,1,n,i,s[i]); } int t; cin>>t; while(t--) { int l,r; cin>>l>>r; ans.cnt=0;ans.gcd=-1;ans.min=INF; query(1,1,n,l,r); if(ans.min!=ans.gcd) cout<<r-l+1<<endl; else cout<<r-l+1-ans.cnt<<endl; } return 0; }
相关文章推荐
- Codeforces Round #271 (Div. 2) F. Ant colony 线段树
- Codeforces Round #271 (Div. 2) F. Ant colony(线段树)
- Codeforces Round #271 (Div. 2) F. Ant colony (RMQ or 线段树)
- Codeforces Round #271 (Div. 2) F. Ant colony
- Codeforces Round #271 (Div. 2) F Ant colony
- Codeforces Round #271 (Div. 2) E. Pillars(线段树优化DP)
- cf/Codeforces Round #373 div1-C/div2-E Sasha and Array 线段树 + 维护矩阵快速幂
- Codeforces Round #373 (Div. 2) E. Sasha and Array 矩阵快速幂+线段树
- Codeforces Round #250 (Div. 1) D 线段树
- Codeforces Round #343 (Div. 2) 629D. Babaei and Birthday Cake 线段树
- Codeforces Round #401 (Div. 2)E. Hanoi Factory(离散化+线段树)
- Codeforces Round #254 (Div. 2) E. DZY Loves Colors(线段树 成段更新)
- Codeforces Round #FF (Div. 2)__E. DZY Loves Fibonacci Numbers (CF447) 线段树
- Codeforces Round #216 (Div. 2) (又是线段树)
- Codeforces Round #399 (Div. 1 + Div. 2, combined) B. Code For 1 线段树
- #Codeforces 343 [div2] D. Babaei and Birthday Cake 【线段树优先队列查询优化】
- CF 242E(div 2) n课线段树更新
- [LCT维护最小生成树 || CDQ分治 || 线段树 并查集 dfs树] Codeforces 603E #334 (Div. 1) E. Pastoral Oddities
- Codeforces Round #333 (Div. 2) B. Approximating a Constant Range (线段树区间最值)
- Codeforces Round #393 (Div. 2) E题Nikita and stack(线段树)解题报告