poj 3368 RMQ做法-實際上不過是dp的變形罷了

來源:互聯網
上載者:User

上一篇是線段樹的做法,這一個是用RMQ方法做的,順便學習一下RMQ。

說是RMQ實際上就是dp的變形。

RMQ定義:

RMQ (Range Minimum/Maximum Query)問題是指:對於長度為n的數列A,回答若干詢問RMQ(A,i,j)(i,j<=n),返回數列A中下標在i,j裡的最小(大)值,也就是說,RMQ問題是指求區間最值的問題。

主要方法及複雜度如下:

  1、樸素(即搜尋),O(n)-O(qn) online。

  2、線段樹,O(n)-O(qlogn) online。

  3、ST(實質是動態規劃),O(nlogn)-O(1) online。

  ST演算法(Sparse Table),以求最大值為例,設d[i,j]表示[i,i+2^j-1]這個區間內的最大值,那麼在詢問到[a,b]區間的最大值時答案就是max(d[a,k], d[b-2^k+1,k]),其中k是滿足2^k<=b-a+1(即長度)的最大的k,即k=[ln(b-a+1)/ln(2)]。

  d的求法可以用動態規劃,d[i, j]=max(d[i, j-1],d[i+2^(j-1), j-1])。

  4、RMQ標準演算法:先規約成LCA(Lowest Common Ancestor),再規約成約束RMQ,O(n)-O(1) online。

  首先根據原數列,建立笛卡爾樹,從而將問題線上性時間內規約為LCA問題。LCA問題可以線上性時間內規約為約束RMQ,也就是數列中任意兩個相鄰的數的差都是+1或-1的RMQ問題。約束RMQ有O(n)-O(1)的線上解法,故整個演算法的時間複雜度為O(n)-O(1)。

 

這裡的狀態方程dp[j][i] = max(dp[j][i - 1], dp[j + (1 <<(i - 1))][i - 1]);

dp[j][i]標示從j開始前2^i個數中最大重複次數。

有了這些,其他和上一篇基本上一樣的,所以代碼極其相似。

 

//RMQ#include <iostream>#include <cmath>using namespace std;int arr[100010],hash[100010];struct Part{int s, e, cnt;}part[100010];int dp[100010][18];//dp[i][j] is for : the max value rang from i to (i + 2^j - 1)int Max(int a, int b){return a >  b ? a : b;}void Dp(int n){int i, j, tmp;for (i = 1; i <= n; ++ i){dp[i][0] = part[i].cnt;}tmp = log(n + 1.0)/log(2.0);for (i = 1; i <= tmp; ++ i){for (j = 1; j + (1 << i) - 1 <= n ; ++ j){dp[j][i] = Max(dp[j][i - 1], dp[j + (1 << (i - 1))][i - 1]);}}}int getMax(int a, int b){int k = (int )((log(b - a + 1.0)) / log(2.0));return Max(dp[a][k], dp[b - (1 << k) + 1][k]);}int main(){int n, q;while (scanf("%d", & n) && n){scanf("%d", & q);for (int i = 1; i <= n; ++ i){scanf("%d", & arr[i]);}memset(part, 0, sizeof(part));int id = 1;part[1].s = id;for (int i = 1; i <= n; ++ i){part[id].cnt ++;hash[i] = id;if (arr[i] != arr[i + 1] || i == n){part[id].e = i;++ id;part[id].s = i + 1;}}Dp(id - 1);int a, b;while (q --){scanf("%d %d", & a, & b);if (hash[a] == hash[b])//the same part{printf("%d\n", b - a + 1);}else// two situations{int n1 = part[hash[a]].e - a + 1;int n2 = b - part[hash[b]].s + 1;int n3 = 0;if (hash[b] - hash[a] > 1){n3 = getMax(hash[a] + 1, hash[b] -  1);}printf("%d\n", Max(Max(n1, n2),n3));}}}return 0;}

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.