• hdu 4630 树状数组


    思路:这题的处理方式和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 ",ans[i]); } return 0; }
  • 相关阅读:
    fibnacci数列递归实现
    求最大公约数伪代码
    第五周学习总结
    第四周学习总结
    我的黑客偶像
    BASE64编码
    第三周学习总结
    第二周学习总结
    Python gui
    SSH实践
  • 原文地址:https://www.cnblogs.com/wangfang20/p/3228369.html
Copyright © 2020-2023  润新知