hdu 5869 求区间不同gcd数 离线+树状数组+rmq二分
2017-06-21 11:22
417 查看
This is a simple problem. The teacher gives Bob a list of problems about GCD (Greatest Common Divisor). After studying some of them, Bob thinks that GCD is so interesting. One day, he comes up with a new problem about GCD. Easy as it looks, Bob cannot figure it out himself. Now he turns to you for help, and here is the problem:
Given an array aa of NN positive integers a1,a2,⋯aN−1,aNa1,a2,⋯aN−1,aN; a subarray of aa is defined as a continuous interval between a1a1 and aNaN. In other words, ai,ai+1,⋯,aj−1,ajai,ai+1,⋯,aj−1,aj is a subarray of aa, for 1≤i≤j≤N1≤i≤j≤N. For a query in the form (L,R)(L,R), tell the number of different GCDs contributed by all subarrays of the interval [L,R][L,R].
Input
There are several tests, process till the end of input.
For each test, the first line consists of two integers NN and QQ, denoting the length of the array and the number of queries, respectively. NN positive integers are listed in the second line, followed by QQ lines each containing two integers L,RL,R for a query.
You can assume that
1≤ai≤10000001≤ai≤1000000
Output
For each query, output the answer in one line.
Sample Input
5 3
1 3 4 6 9
3 5
2 5
1 5
Sample Output
6
6
6
给n个数,m个询问,问区间l,r 的gcd种类总数
求区间不同数,在线的用主席树,离线的用树状数组,显然离线+树状数组比较简单。
先把查询排个序
就是每求到一个数 把前面所有的的gcd 往右移,那么gcd就在最接近右边界的地方,那么对于q[i].r==i 的询问,直接用树状数组进行统计即可,如果 有 多个数,只保留最右的一个所在位置,是思想核心 不断的消去和右移
Given an array aa of NN positive integers a1,a2,⋯aN−1,aNa1,a2,⋯aN−1,aN; a subarray of aa is defined as a continuous interval between a1a1 and aNaN. In other words, ai,ai+1,⋯,aj−1,ajai,ai+1,⋯,aj−1,aj is a subarray of aa, for 1≤i≤j≤N1≤i≤j≤N. For a query in the form (L,R)(L,R), tell the number of different GCDs contributed by all subarrays of the interval [L,R][L,R].
Input
There are several tests, process till the end of input.
For each test, the first line consists of two integers NN and QQ, denoting the length of the array and the number of queries, respectively. NN positive integers are listed in the second line, followed by QQ lines each containing two integers L,RL,R for a query.
You can assume that
1≤N,Q≤1000001≤N,Q≤100000
1≤ai≤10000001≤ai≤1000000
Output
For each query, output the answer in one line.
Sample Input
5 3
1 3 4 6 9
3 5
2 5
1 5
Sample Output
6
6
6
给n个数,m个询问,问区间l,r 的gcd种类总数
求区间不同数,在线的用主席树,离线的用树状数组,显然离线+树状数组比较简单。
先把查询排个序
就是每求到一个数 把前面所有的的gcd 往右移,那么gcd就在最接近右边界的地方,那么对于q[i].r==i 的询问,直接用树状数组进行统计即可,如果 有 多个数,只保留最右的一个所在位置,是思想核心 不断的消去和右移
#include <bits/stdc++.h> using namespace std; #define lowbit(x) (x)&(-x) const int N = 102000; int f [20]; int nu ,tr ,n,m,ans ; map<int,int> mp; void add(int x,int val) { while(x<N-50) { tr[x]+=val; x+=lowbit(x); } } int sum(int x) { int res=0; while(x>0) { res+=tr[x]; x-=lowbit(x); } return res; } int gcd(int a,int b) { return (b==0)?a:gcd(b,a%b); } struct node { int l,r,id; }q ; int cmp(node a,node b) { if(a.r==b.r) return a.l<b.l; return a.r<b.r; } void init() { for(int i=1;i<=n;i++) f[i][0]=nu[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]); } } } int rmq(int i,int j) { int k=0; while(1<<(k+1)<=(j-i+1)) k++; return gcd(f[i][k],f[j-(1<<k)+1][k]); } int main() { while(scanf("%d%d",&n,&m)!=EOF) { mp.clear(); memset(tr,0,sizeof(tr)); for(int i=1;i<=n;i++) scanf("%d",&nu[i]); init(); for(int i=1;i<=m;i++) { scanf("%d%d",&q[i].l,&q[i].r); q[i].id=i; } sort(q+1,q+m+1,cmp); int tot=1; for(int i=1;i<=n;i++) { int l=1,r=i; int g=nu[i]; int j=i; while(r>=1) { l=1; while(l<=r) { int mid=(l+r)>>1; if(rmq(mid,i)==g) { r=mid-1; } else l=mid+1; } if(!mp[g]) { add(j,1); } else if(mp[g]<j&&mp[g]) { add(mp[g],-1); add(j,1); } mp[g]=j; g=rmq(r,i); j=r; } while(tot<=m&&q[tot].r==i) { ans[q[tot].id]=sum(q[tot].r)-sum(q[tot].l-1); tot++; } } for(int i=1;i<=m;i++) printf("%d\n",ans[i] ); } }
相关文章推荐
- HDU 5869 求区间中不同连续序列的gcd的个数(树状数组)
- HDU 5869 区间不同GCD的个数
- hdu 5869 (求区间不同gcd的个数)
- Hdu-5869 Different GCD Subarray Query(区间不同值离线算法)
- HDU 5869 Different GCD Subarray Query(计数区间不同GCD)
- hdu 5869 区间不同GCD个数(树状数组)
- HDU - 5869 Different GCD Subarray Query GCD+离线+树状数组(区间不同gcd的个数)
- hdu 5869 区间内不同的GCD数(离线+树状数组)
- 离线记录+树状数组(hdu 5869 统计任意区间的不同gcd值)
- HDU 5869区间CGD不同种类数---树状数组+map统计区间不同种类数(离线)
- [区间GCD预处理 树状数组 离线] HDU 5869 Different GCD Subarray Query
- HDU 5869 Different GCD Subarray Query [区间gcd预处理+离线]【数据结构】
- hdu 4622 求区间不同子串数 后缀数组|后缀自动机|字符串hash
- hdu 5786 Interval 区间gcd求和
- hdu5869——Different GCD Subarray Query(思考+树状数组)
- hdu5869——Different GCD Subarray Query(思考+树状数组)
- hdu_5726_GCD(线段树维护区间+预处理)
- HDU 5869 Different GCD Subarray Query (数学gcd+树状数组离线查询)
- hdu 5726(区间gcd)
- hdu 5726 GCD (线段树 + 区间预处理)