您的位置:首页 > 其它

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被该查询区间所覆盖。

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: