这道题的暴力很好写。。
正解也很暴力。。。(PS:吐槽数据。。说好的≤100000却出现了100001)
正解分块。
主要思路是处理出每个块对于每个模数的最大余数。乍一看好想只能(那我优化什么???)
其实可以。。因为可以处理出块内到每个数为止的最大值。之后枚举每个数作为模数,再枚举起始点,
起始点+模数-1,也就是加上最大余数,在这个范围内的最大的数%模数就是要求的最大模数。。
这样的时间就是也就是而后面就是调和级数,时间是,这样最终的时间就是块数。
那么为了时间,我们去共块,这样总时间就是,就不会超时了。
而的最大情况就是1e5*(11.512925464970228420089957273422)差不多为10,那么分1000块比较好。
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define N 100000
using namespace std;
int n,m,l,r,k;;
int val[100005];
int f[100005];
int blg=1000;
int mx[105][100005];
int main()
{
freopen("flower.in","r",stdin);
freopen("flower.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&val[i]);
}
int num=(n-1)/blg+1;
for(int i=1;i<=num;i++)
{
memset(f,0,sizeof(f));
int l=(i-1)*blg+1,r=min(i*blg,n);
for(int j=l;j<=r;j++)f[val[j]]=val[j];
for(int j=1;j<=N;j++)f[j]=max(f[j],f[j-1]);
for(int j=1;j<=N;j++)
{
for(int k=0;k<=N;k+=j)
{
mx[i][j]=max(mx[i][j],f[min(k+j-1,N)]-k);
}
}
}
for(int i=1;i<=m;i++)
{
int l,r,k;
scanf("%d%d%d",&l,&r,&k);
int l1=(l-1)/blg+1,r1=(r-1)/blg+1;
int ans=0;
for(int j=l1+1;j<=r1-1;j++)
{
ans=max(ans,mx[j][k]);
}
for(int j=l;j<=min(l1*blg,r);j++)
{
ans=max(ans,val[j]%k);
}
for(int j=max((r1-1)*blg+1,l);j<=r;j++)
{
ans=max(ans,val[j]%k);
}
printf("%d\n",ans);
}
return 0;
}