描述
從前有個人名叫W and N and B,他有着天才般的記憶力,他珍藏了許多許多的寶藏。在他離世之後留給後人一個難題(專門考驗記憶力的啊!),如果誰能輕鬆回答出這個問題,便可以繼承他的寶藏。題目是這樣的:給你一大串數字(編號爲1到N,大小可不一定哦!),在你看過一遍之後,它便消失在你面前,隨後問題就出現了,給你M個詢問,每次詢問就給你兩個數字A,B,要求你瞬間就說出屬於A到B這段區間內的最大數。一天,一位美麗的姐姐從天上飛過,看到這個問題,感到很有意思(主要是據說那個寶藏裏面藏着一種美容水,喝了可以讓這美麗的姐姐更加迷人),於是她就竭盡全力想解決這個問題。BUT,她每次都以失敗告終,因爲這數字的個數是在太多了!於是她請天才的你幫他解決。如果你幫她解決了這個問題,可是會得到很多甜頭的哦!
格式
輸入格式
一個整數N表示數字的個數,接下來一行爲N個數。第三行讀入一個M,表示你看完那串數後需要被提問的次數,接下來M行,每行都有兩個整數A,B。
輸出格式
輸出共M行,每行輸出一個數。
提示
對於30%的數據,1<=N<=10000,1<=M<=100
對於100%的數據,1<=N<=200000,1<=M<=10000.
題解
RMQ裸題。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<cmath>
#include<algorithm>
#define MAXN 200002
using namespace std;
int n,m,bin[20],L[MAXN],f[MAXN][20];
void init()
{
scanf("%d",&n);
int i,j;
for(i=1;i<=n;i++) scanf("%d",&f[i][0]);
bin[0]=1; L[0]=-1;
for(i=1;i<=18;i++) bin[i]=bin[i-1]<<1;
for(i=1;i<=n;i++) L[i]=L[i>>1]+1;
for(j=1;j<=18;j++)
for(i=1;i+bin[j]-1<=n;i++)
f[i][j]=max(f[i][j-1],f[i+bin[j-1]][j-1]);
}
int find(int l,int r)
{
int t=r-l+1,mi;
mi=L[t];
return max(f[l][mi],f[r-bin[mi]+1][mi]);
}
void work()
{
scanf("%d",&m);
int x,y;
while(m--)
{scanf("%d%d",&x,&y);
printf("%d\n",find(x,y));
}
}
int main()
{
init(); work();
return 0;
}