区间最大值(数论分块)
题意
长度为\(n\)的数组\(a\),下标从\(1\)开始,定义\(a_i = n % i\)。
有\(m\)组询问\(L, R\),求\(\max\limits_{i = L}^R a_i\)
数据范围
\(n \leq 10^8\)
\(m \leq 10^4\)
\(1 \leq L \leq R \leq n\)
思路
由\(a_i = n \% i = n - \lfloor n / i \rfloor * i\),则区间最大值相当于求\(\lfloor n / i \rfloor * i\)的最小值。
而\(\lfloor n / i \rfloor\)只有\(2\sqrt n\)个不同的取值。对每个\(\lfloor n / i \rfloor\)的取值,要使\(n \% i\)最大则\(i\)应尽量小(也就是求每一块的左端点)。故用数论分块的方法扫一遍即可。
代码
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
int n, m;
scanf("%d%d", &n, &m);
while(m --) {
int a, b;
scanf("%d%d", &a, &b);
int ans = n - (n / a) * a;
for(int l = a, r; l <= b; l = r + 1) {
r = n / (n / l);
ans = max(ans, n - (n / l) * l);
}
printf("%d\n", ans);
}
return 0;
}