hdu 4630 No Pain No Game

时间:2023-03-09 12:51:22
hdu 4630 No Pain No Game

http://acm.hdu.edu.cn/showproblem.php?pid=4630

离散化+树状数组

将数组 *a  从后向前遍历 遍历到 a[x] 的时候 再枚举a[x]的约数 假如 约数 k

last[k] 对应到 上一个k出现的位置  那么可被公约数 k 更新的区间是   last[k] --- 最后

把所有a[x]的约数都处理完之后  从 x 到任意 y(y>=x)形成的段的 最优解都可求

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<cmath>
#include<set>
#include<vector>
#include<list>
using namespace std; typedef long long ll;
typedef pair<double,double>ppd;
const double PI = acos(-1.);
const double eps = (1e-9);
const int N=50001;
struct node
{
int l,r;
int index;
}q[N];
int a[N],last[N],ans[N];
int c[N];
int lowbit(int x)
{
return x&(-x);
}
void update(int i,int k)
{
while(i<N)
{
c[i]=max(c[i],k);
i+=lowbit(i);
}
}
int getM(int i)
{
int tmp=0;
while(i>=1)
{
tmp=max(tmp,c[i]);
i-=lowbit(i);
}
return tmp;
}
bool cmp(const node &x,const node &y)
{
return x.l>y.l;
}
int main()
{
//freopen("data.in","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
int Q;
scanf("%d",&Q);
for(int i=0;i<Q;++i)
{
scanf("%d %d",&q[i].l,&q[i].r);
q[i].index=i;
}
sort(q,q+Q,cmp);
memset(c,0,sizeof(c));
memset(last,-1,sizeof(last));
int ln=0;
for(int i=n;i>=1;--i)
{
for(int x=1;x*x<=a[i];++x)
if(a[i]%x==0)
{
if(last[x]!=-1)
update(last[x],x);
last[x]=i;
int y=a[i]/x;
if(x==y)
continue;
if(last[y]!=-1)
update(last[y],y);
last[y]=i;
}
while(ln<Q&&q[ln].l==i)
{
ans[q[ln].index]=getM(q[ln].r);
++ln;
}
}
for(int i=0;i<Q;++i)
printf("%d\n",ans[i]);
}
return 0;
}