其實咱們求 dp[i][j] 的時候能夠把它分紅兩部分,第一部分是從 i 到 i + 2 ^( j-1 ) - 1 ,第二部分從 i + 2 ^( j-1 ) 到i + 2^j -1 ,爲何能夠這麼分呢?其實咱們都知道二進制數前一個數是後一個的兩倍,那麼能夠把 i ~ i + 2^j -1 這個區間 經過2^(j-1) 分紅相等的兩部分, 那麼轉移方程很容易就寫出來了。(dp[i][0]就表示第i個數字自己)spa
dp[i][j] = min(dp [i][j - 1], dp [i + (1 << j - 1)][j - 1])
code
1 void rmq_init() 2 { 3 for(int i=1;i<=N;i++) 4 dp[i][0]=arr[i];//初始化 5 for(int j=1;(1<<j)<=N;j++) 6 for(int i=1;i+(1<<j)-1<=N;i++) 7 dp[i][j]=min(dp[i][j-1],dp[i+(1<<j-1)][j-1]); 8 } 9 10 int rmq(int l,int r) 11 { 12 int k=log2(r-l+1); 13 return min(dp[l][k],dp[r-(1<<k)+1][k]); 14 } 15 16