区间最大值(数论分块)

题意

长度为\(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;
}
posted @ 2022-03-30 21:42  pbc的成长之路  阅读(165)  评论(0编辑  收藏  举报