ST表——模板(luogu3865)
阿新 • • 發佈:2018-09-04
ima 個數 col set style 數字 -m || 技術
題目背景
這是一道ST表經典題——靜態區間最大值
請註意最大數據時限只有0.8s,數據強度不低,請務必保證你的每次查詢復雜度為 O(1)
題目描述
給定一個長度為 N 的數列,和 M 次詢問,求出每一次詢問的區間內數字的最大值。
輸入輸出格式
輸入格式:
第一行包含兩個整數 N, M ,分別表示數列的長度和詢問的個數。
第二行包含 N 個整數(記為 ai),依次表示數列的第 i 項。
接下來 M 行,每行包含兩個整數 li, ri,表示查詢的區間為 [ li, ri ]
輸出格式:
輸出包含 M 行,每行一個整數,依次表示每一次詢問的結果。
輸入輸出樣例
輸入樣例8 8 9 3 1 7 5 6 0 8 1 6 1 5 2 7 2 6 1 8 4 8 3 7 1 8輸出樣例
9
9
7
7
9
8
7
9
講解:
作用——O(nlogn)預處理,O(1) 求區間最大值
思想——倍增
設一個Max[ i ][ j ] 表示從 i 位置 ,長度2j 的區間最大值
以樣例為例
9 3 1 7 5 6 0 8
Max[1][1]=9
Max[2][1]=3
Max[3][1]=7
Max[4][1]=7
Max[5][1]=6
Max[6][1]=6
Max[7][1]=8
Max[1][2]=9
Max[2][2]=7
Max[3][2]=7
Max[4][2]=7
Max[5][2]=8
Max[1][3]=9
查詢(如圖)
算出 k=log2(區間長度) ,等同於:
for(k=0;(1<<k)<=r-l+1;k++) ;
k--;
就好啦,很簡單吧~個鬼
std代碼
#include<cstdio> #include<cmath> #include<algorithm> using namespace std; const int MAXN=1e6+10; int read() { char c=getchar();int x=0,f=1; while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();} while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();}return x*f; } int Max[MAXN][21]; int Query(int l,int r) { int k=log2(r-l+1); return max(Max[l][k],Max[r-(1<<k)+1][k]); } int main() { int N=read(),M=read(); for(int i=1;i<=N;i++) Max[i][0]=read(); for(int j=1;j<=21;j++) for(int i=1;i+(1<<j)-1<=N;i++) { Max[i][j]=max(Max[i][j-1],Max[i+(1<<(j-1))][j-1]); // printf("Max[%d][%d]=%d\n",i,j,Max[i][j]); } for(int i=1;i<=M;i++) { int l=read(),r=read(); printf("%d\n",Query(l,r)); } return 0; }
ST表——模板(luogu3865)