hdu 4630 树状数组 ****
2015-07-04 10:47
344 查看
题意:Given you a sequence of number a1, a2, ..., an.They are also a permutation of 1...n.
You need to answer some queries,each with the following format:
If we chose two number a,b (shouldn't be the same) from interval [l,
r],what is the maximum gcd(a, b)? If there's no way to choose two
distinct number(l=r) then the answer is zero.
思路:这题的处理方式和hdu4358有点像。我们用一个pre[x]表示约数x的倍数上次出现的位置,将查询按区间的右节点升序排序。num[i]的约 数为j,如果pre[j]为0,就将pre[j]置为i;否则就update(pre[j],j),表示的意思是约数j肯定不是第一次出现,将 pre[j]以前的区间更新最大约数。如果查询区间的右边界在i处,那么左边界在pre[j]以前就肯定就能取到j。因为num[pre[j]]和 num[i]有一个公共约数j,且pre[j]和i被该查询区间所覆盖。
You need to answer some queries,each with the following format:
If we chose two number a,b (shouldn't be the same) from interval [l,
r],what is the maximum gcd(a, b)? If there's no way to choose two
distinct number(l=r) then the answer is zero.
思路:这题的处理方式和hdu4358有点像。我们用一个pre[x]表示约数x的倍数上次出现的位置,将查询按区间的右节点升序排序。num[i]的约 数为j,如果pre[j]为0,就将pre[j]置为i;否则就update(pre[j],j),表示的意思是约数j肯定不是第一次出现,将 pre[j]以前的区间更新最大约数。如果查询区间的右边界在i处,那么左边界在pre[j]以前就肯定就能取到j。因为num[pre[j]]和 num[i]有一个公共约数j,且pre[j]和i被该查询区间所覆盖。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define Maxn 50010 #define lowbit(x) (x&(-x)) using namespace std; int C[Maxn],n,num[Maxn],pre[Maxn],q,ans[Maxn]; struct QT{ int l,r,i; int operator <(const QT &temp) const { return r<temp.r; } }qt[Maxn]; int Sum(int pos)//往后找 { int sum=0; while(pos<=n) { sum=max(sum,C[pos]); pos+=lowbit(pos); } return sum; } void update(int pos,int val)//更新pos以前的位置 { while(pos) { C[pos]=max(C[pos],val); pos-=lowbit(pos); } } int main() { int t,i,j; scanf("%d",&t); while(t--) { memset(C,0,sizeof(C)); memset(pre,0,sizeof(pre)); scanf("%d",&n); for(i=1;i<=n;i++) scanf("%d",num+i); scanf("%d",&q); for(i=1;i<=q;i++) { scanf("%d%d",&qt[i].l,&qt[i].r); qt[i].i=i; } sort(qt+1,qt+1+q); int r=1; for(i=1;i<=n;i++) { if(r>q) break; for(j=1;j*j<=num[i];j++) { if(num[i]%j) continue; if(pre[j]) update(pre[j],j); pre[j]=i; if(j*j==num[i]) break; int k=num[i]/j; if(pre[k]) update(pre[k],k); pre[k]=i; } while(qt[r].r==i&&r<=q) { ans[qt[r].i]=Sum(qt[r].l); r++; } } for(i=1;i<=q;i++) printf("%d\n",ans[i]); } return 0; }
相关文章推荐
- 微信公众平台开发--OAuth2.0网页授权
- FastMM使用方法总结
- OC特性
- C# 使用SerialPort控件用类及线程实现串口通信
- JavaScript的作用域和变量对象
- php面向对象编程--抽象类
- leetcode 34: Search for a Range
- 四、cocos2d-x的弹窗弹性动画
- DHCP服务安装配置
- Object-c 中的数据类型
- Android--AIDL,一种实现进程间通信的方式
- 真正的Hybrid APP没你想的那么简单
- iCloud
- EGOCache缓存框架详细讲解
- Spring MVC @Transactional注解方式事务失效的解决办法
- iOS 发布证书申请 (转载)
- uva 270 Linin g Up
- android生成apk包出现Unable to add "XXX" Zip add failed问题
- C# Winform反序列化复杂json字符串
- NPM使用详解(上)