RMQ學習總結(附帶簡單例題)

2021-09-19 13:15:56 字數 3623 閱讀 9880

rmq (range minimum/maximum query)問題

含義:對於長度為n的數列a,回答若干詢問rmq(a,i,j)(i,j<=n),返回數列a中下標在i,j裡的最小(大)值,也就是說,rmq問題是指求區間最值的問題。

時間複雜度:預處理時間複雜度o(n*log(n)),查詢o(1)

基礎:dp

f[i][j]表示從第i位起,2^j個數中的最值。

那麼dp的初值是什麼?

顯然f[i][0]的值為a[i]。

dp的方程呢?

對於i~i+2^j-1這段區間,我們將它分為長度相同的兩部分:

顯然2j=2(j-1)+2(j-1),所以分為i~i+2(j-1)-1, i+2(j-1)~i+2j-1;

那麼f[i][j]=max/min(f[i][j-1],f[i+2^(j-1)][j-1])。

所以當查詢一段區間[l,r]時:

int k=trunc(log2(r-l+1));

int ans=max/min(f[l][k],f[r-2^k+1][k]);

description

現給你n(<=1000000)個整數(都小於longint),有k(0< k<= 1000000)個詢問,對於每個詢問(l,r),回答(l,r)內的最大值為多少?

input

第一行兩個整數n和k;第二行為n個整數,第三行到第k+2行為k個詢問;

output

共k行,每行為乙個詢問的最大值

sample input

10 2

3 2 4 5 6 8 1 2 9 7

1 82 9

sample output89

顯然這是一道非常裸的rmq問題,只需維護max即可。

#include #include #include #include #include #include #include #include #include #include #include #define mod 1e9+7

#define inf 0x3f3f3f3f

#define lson l,m,rt<<1

#define rson m+1,r,rt<<1|1

typedef unsigned long long ull;

typedef long long ll;

using namespace std;

int n,k,a[1000005];

int dp[100005][25];

void rmq_init()

for(int j=1;(1在每天**的時候,農民約翰的n頭牛(1≤n≤50000)總是排成一列。有一天,約翰決定與他的牛們一起玩乙個極限飛盤遊戲。為了簡單起見,他將從奶牛佇列裡面選一定範圍內的奶牛來玩這個遊戲。然而所有的牛對這個遊戲都很感興趣。農民約翰列出了q份名單(1≤q≤200000)和每個奶牛的高度(1≤高度≤1000000)。對於每乙份名單,他想你幫助他確定在每份名單中高度最高的奶牛與高度最低的奶牛的高度差是多少。

input

第一行為n(1≤n≤50000)和q(1≤q≤200000);從第2行到第n+1行,每行乙個數字,表示第i頭牛的高度(1≤height≤1000000);從第n+2行到第n+q+1行,每行兩個整數a和b(1≤a≤b≤n),表示從第a頭牛到第b頭牛的範圍。

output

從第一行到第q行,每行乙個整數,表示從第a頭牛到第b頭牛之間,最高牛與最矮牛的高度差。

sample input

6 3173

4251 5

4 62 2

sample output63

0下面貼出**:

#include #include #include #include #include #include #include #include #include #include #include #define mod 1e9+7

#define inf 0x3f3f3f3f

#define lson l,m,rt<<1

#define rson m+1,r,rt<<1|1

typedef unsigned long long ull;

typedef long long ll;

using namespace std;

int n,m,dp[500005][25],dptiny[500005][25];

int a[500005];

void rmq_init()

for(int j=1;(1<#3 poj3368

description

給你乙個含有n個整數的非遞減序列a1 , a2 , … , an,要求你回答一系列的詢問,如i和j (1 ≤ i ≤ j ≤ n),回答出ai , … , aj之間出現頻率最多數字為多少次?

input

輸入檔案包含多組資料,每組資料的第1行包含兩個整數n和q(1 ≤ n, q ≤ 100000),第2行為n個用空格分開的整數a1 , … , an (-100000 ≤ ai ≤ 100000, for each i ∈ ),接下來的q行,每行包含兩個整數i和j。檔案以0作為結束標記。

output

對於每乙個詢問輸出一行,為在此區間內出現頻率最多數字為多少次?

sample input

10 314

3hint

【資料範圍】

對於30的資料,1≤n,q≤1000;

對於100的資料,1≤n,q≤1000000;

這道終於不太裸了。。。

f陣列表示是連續的相同數塊中的第幾位。

例如:題目中的資料

a:-1 -1 1 1 1 1 3 10 10 10

f:1 2 1 2 3 4 1 1 2 3

對於每個詢問[l,r]

首先找到在序列中和a[l]值相同且連續的最大位置,即下面**中的t。

那麼對於[t,r]這段區間中,f[i]的最大值就是頻率最大的數的頻率。

用rmq處理最大值。

再用它與(t-l)比較,更新答案。

下面貼出**:

#include #include #include #include #include #include #include #include #include #include #include #define mod 1e9+7

#define inf 0x3f3f3f3f

#define lson l,m,rt<<1

#define rson m+1,r,rt<<1|1

typedef unsigned long long ull;

typedef long long ll;

using namespace std;

int n,q;

int m[100005][20];

int f[100005];

int a[100005];

void st_prepare()

int main()

st_prepare();

for(int i=1; i<=n; i++)cout

for(int i=1; i<=q; i++)

cout

return 0;

}

本週學習總結(C語言的簡單例題)

1.實現數字金字塔 i 行數 j 空格數 n 金字塔的層數 include int main for a i a 1 a printf n 2.實現字母金字塔 第乙個思路和數字的類似,就是比較麻煩。include int main for a i 1 a 1 a printf n 第二個思路 直接用...

區間DP例題總結 看似不簡單的簡單題

今天,我們開始學那奇怪的區間dp。簡單來說,區間dp分為三個部分 階段列舉左端點,再列舉右端點 策略 顧名思義就是因為有些題,需要求出中點k,但有些題卻又不需要。所以我們應該判斷,用與不用。現在我們來看幾道經典例題 n堆石子擺成一條線。現要將石子有次序地合併成一堆。規定每次只能選相鄰的2堆石子合併成...

rollup學習 簡單總結

官方教程 例子 github位址 新建my rollup project檔案 my rollup project目錄下npm init or yarn init 新建foo.js,main.js,index.html 結構如下圖所示 直接執行npm run build or npm run buil...