這道題的暴力很好寫。。
正解也很暴力。。。(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;
}