hdu 5869 求区间不同gcd数 离线+树状数组+rmq二分
来源:互联网 发布:淘宝店页头尺寸 编辑:程序博客网 时间:2024/05/30 19:34
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≤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[N][20];int nu[N],tr[N],n,m,ans[N];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[N];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数 离线+树状数组+rmq二分
- hdu 5869 区间内不同的GCD数(离线+树状数组)
- hdu 5869 RMQ+二分+离线树状数组
- 离线记录+树状数组(hdu 5869 统计任意区间的不同gcd值)
- HDU 5869区间CGD不同种类数---树状数组+map统计区间不同种类数(离线)
- HDU 5869 求区间中不同连续序列的gcd的个数(树状数组)
- 【HDU 3333】【离线询问 树状数组 前驱思想】Turing Tree【 求区间中不同的数的和】
- [区间GCD预处理 树状数组 离线] HDU 5869 Different GCD Subarray Query
- BZOJ 题目1878: [SDOI2009]HH的项链(树状数组离线求区间不同种类数)
- HDU 5726 求gcd=k的区间的个数 (二分+RMQ)
- HDU 5869 Different GCD Subarray Query 离线 树状数组
- hdu 5869 Different GCD Subarray Query 离线+树状数组
- HDU 5869 Different GCD Subarray Query(离线处理+树状数组)
- HDU 5869 Different GCD Subarray Query (离线处理 树状数组)
- hdu4777 Rabbit Kingdom 离线树状数组 求询问区间内的区间数
- hdu 4630 树状数组+离线操作+GCD
- hdu 5726 gcd rmq 求相同gcd的区间数量
- HDU 4417 - Super Mario (求区间小于h的数 划分树 二分 线段树 树状数组)
- mongodb设置用户名密码,以及权限
- listView的item变化以及颜色选择,点其它控件默认对listView的选中项,排序
- 深入理解java异常处理机制
- Git 提交代码到github
- ROW_NUMBER() OVER函数的基本用法 / Rank() over()的用法
- hdu 5869 求区间不同gcd数 离线+树状数组+rmq二分
- Redis安装
- $* $@
- Linux版Oracle数据库的基本操作
- VMware下桥接设置
- java 堆、栈、方法区/ 类变量、成员变量、局部变量
- yum安装net-snmp引发的libssl.so.10失效导致yum不可用问题
- 在Debian 8上试图激活Gentoo的SELinux Policy
- 前端杂记(1):表单提交验证、input(type=number) 去三角,刷新验证码