vijos P1514 天才的記憶

描述

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

格式

輸入格式

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

輸出格式

輸出共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.

題解

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;
}
發佈了367 篇原創文章 · 獲贊 2 · 訪問量 26萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章