hdu 4630 多校第二场 树状数组,离线处理

 1-n的排列,询问(l,r)之间的最大的gcd(a,b)
(1)离线处理,询问对按右端点排序,边插入边查询,使在处理(l,r)时,(l,r)内的该插入的已经插入
(2)枚举每个数的约数,记录到当前位置为止,上一个x的倍数出现的位置prev(x)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
#define N 100500
struct Q
{
    int l,r,idx;
}que[N];
int b[N],ans[N],n,q,a[N];

bool cmp(Q ll, Q rr)
{
    return ll.r<rr.r;
}
void update(int x,int val)
{
    while(x)
    {
        b[x]=max(b[x],val);
        x-=x&(-x);
    }
}
int query(int x)
{
    int res=0;
    while(x<=n)
    {
        res=max(res,b[x]);
        x+=x&(-x);
    }
    return res;
}
vector<int>divs[N];
int pre[N];
int main ()
{
    for(int i=1;i<N;++i)
        for(int j=i;j<N;j+=i)
        divs[j].push_back(i);
    int T;scanf("%d",&T);
    while(T--)
    {
        memset(b,0,sizeof(b));
        memset(pre,0,sizeof(pre));
        scanf("%d",&n);
        for(int i=1;i<=n;++i)
            scanf("%d",&a[i]);
        scanf("%d",&q);
        int u,v;
        for(int i=1;i<=q;++i)
        {
            scanf("%d%d",&u,&v);
            que[i].l=u;que[i].r=v;que[i].idx=i;
        }
        sort(que+1,que+1+q,cmp);
        for(int i=1,k=1;i<=n;++i)
        {
            int x=a[i];
            for(int j=0;j<divs[x].size();++j)
            {
                int pp=divs[x][j];
                if(pre[pp])
                    update(pre[pp],pp);
                pre[pp]=i;
            }
            while(que[k].r==i&&k<=q)
            {
                ans[que[k].idx]=query(que[k].l);
                k++;
            }
        }
        for(int i=1;i<=q;++i)
            printf("%d\n",ans[i]);
    }
    return 0;
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值