[Vijos] 天才的記憶

背景

神仙飛啊飛spa

描述

從前有我的名叫W and N and B,他有着天才般的記憶力,他珍藏了許多許多的寶藏。在他離世以後留給後人一個難題(專門考驗記憶力的啊!),若是誰能輕鬆回答出這個問題,即可以繼承他的寶藏。題目是這樣的:給你一大串數字(編號爲1到N,大小可不必定哦!),在你看過一遍以後,它便消失在你面前,隨後問題就出現了,給你M個詢問,每次詢問就給你兩個數字A,B,要求你瞬間就說出屬於A到B這段區間內的最大數。一天,一位美麗的姐姐從天上飛過,看到這個問題,感到頗有意思(主要是聽說那個寶藏裏面藏着一種美容水,喝了能夠讓這美麗的姐姐更加迷人),因而她就不遺餘力想解決這個問題。BUT,她每次都以失敗了結,由於這數字的個數是在太多了!因而她請天才的你幫他解決。若是你幫她解決了這個問題,但是會獲得不少甜頭的哦!code

格式

輸入格式

一個整數N表示數字的個數,接下來一行爲N個數。第三行讀入一個M,表示你看完那串數後須要被提問的次數,接下來M行,每行都有兩個整數A,B。blog

輸出格式

輸出共M行,每行輸出一個數。繼承

樣例1

樣例輸入1

6
34 1 8 123 3 2
4
1 2
1 5
3 4
2 3

樣例輸出1

34
123
123
8

提示

對於30%的數據,1<=N<=10000,1<=M<=100
對於100%的數據,1<=N<=200000,1<=M<=10000.io

思路class

st表;數據

f[i][j]表示從i開始,包含1<<j個元素的區間的區間最大值;查詢

轉移方程:f[i][j]=max_(f[i][j-1],f[i+(1<<j-1)][j-1];di

查詢(l,r):co

p=log2(r-l+1);

max(l,r)=max_(f[l][p],f[r-(1<<p)+1][p]);

代碼實現

 1 #include<cmath>
 2 #include<cstdio>
 3 const int maxn=2e5+10;
 4 inline int max_(int x,int y){return x>y?x:y;}
 5 int n,m,l,a,b;
 6 int f[maxn][32];
 7 int main(){
 8     scanf("%d",&n);
 9     for(int i=1;i<=n;i<<=1) l++;
10     for(int i=1;i<=n;i++) scanf("%d",&f[i][0]);
11     for(int i=1;i<l;i++) for(int j=1;j<=n;j++)
12     if(j+(1<<i-1)<=n) f[j][i]=max_(f[j][i-1],f[j+(1<<i-1)][i-1]);
13     else f[j][i]=f[j][i-1];
14     scanf("%d",&m);
15     for(int i=1;i<=m;i++){
16         scanf("%d%d",&a,&b);
17         l=log2(b-a+1);
18         printf("%d\n",max_(f[a][l],f[b-(1<<l)+1][l]));
19     }
20     return 0;
21 }
相關文章
相關標籤/搜索