1. 程式人生 > >2018/2/17 每日一學 RMQ

2018/2/17 每日一學 RMQ

pre 區間dp 什麽是 極值 ++ 想想 i++ i+1 bsp

什麽是RMQ?

給予n個數,對於區間[l,r]查詢最小、最大值。

這就是RMQ。

怎麽做?

我們不妨設f[i][j]表示從i開始的2^j個數極值。

顯然,他表示的是[i,i+2^j-1],註意有-1(想想,為什麽?)

那麽我們不難得到遞推式:f[i][j]=min/max(f[i][j-1]+f[i+1<<(j-1)+1][j-1]。

註意先枚舉j,聯系以下區間dp不難明白為什麽先枚舉j。

最後怎麽查詢???

很簡單,分治的思想。

假設我們查詢[x,y],則ans=max/min([x][k],[y-1<<k+1][k].

這個k怎麽求,由題意得:x+2^k>=y-2^k+1.

得,y-x+1<=2^(k+1)

所以就很簡單了,k=log2(y-x+1)

看代碼吧:

void ST(int n) {
    for (int i = 1; i <= n; i++)
        dp[i][0] = A[i];
    for (int j = 1; (1 << j) <= n; j++) {
        for (int i = 1; i + (1 << j) - 1 <= n; i++) {
            dp[i][j] = max(dp[i][j - 1], dp[i + (1 << (j - 1
))][j - 1]); } } } int RMQ(int l, int r) { int k = 0; while ((1 << (k + 1)) <= r - l + 1) k++; return min(dp[l][k], dp[r - (1 << k) + 1][k]); }

2018/2/17 每日一學 RMQ