1. 程式人生 > 其它 >區間最大值(數論分塊)

區間最大值(數論分塊)

題意

長度為\(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;
}