並不對勁的st表
阿新 • • 發佈:2018-01-30
math putchar 個數 string return 個性 ring () using
對於帶修改的區間求和能做到O(n log n)預處理,O(log n)查詢;而不帶修改的可以做到O(n)預處理,O(1)查詢。那麽不帶修改的區間最值能做到O(1)查詢嗎?
區間最值有這樣一個性質:對於一段區間的兩個子區間,如果它們覆蓋了整個區間(可以有重疊部分),那麽這兩段區間各自的最大(或最小)值的最大(或最小)值就等於整個區間的最大(或最小)值。
這樣的話,可以倍增地求出從每個位置開始的2的x次方的區間最值,預處理每個數的log。查詢l-r這一段區間時按如圖所示的方式合並就行了。
#include<iostream> #include<iomanip> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #define maxn 100010 using namespace std; int read() { int f=1,x=0;char ch=getchar(); while(isdigit(ch)==0 && ch!=‘-‘)ch=getchar(); if(ch==‘-‘)f=-1,ch=getchar(); while(isdigit(ch))x=x*10+ch-‘0‘,ch=getchar(); return x*f; } void write(int x) { int ff=0;char ch[15]; if(x<0) { x=-x; putchar(‘-‘); } while(x)ch[++ff]=(x%10)+‘0‘,x/=10; if(ff==0)putchar(‘0‘); while(ff)putchar(ch[ff--]); putchar(‘\n‘); } struct ST { int st[maxn][20],logx[maxn],two[maxn]; int n,q,l,r; void ask() { l=read(),r=read(); write(max(st[l][logx[r-l+1]],st[r-two[r-l+1]+1][logx[r-l+1]])); } void work() { n=read(),q=read(); for(int i=1,j=1,k=0;i<=n;i++) { st[i][0]=read(); if((j<<1)<=i)j<<=1,k++; logx[i]=k; two[i]=j; } for(int i=1;(1<<i)<=n;i++) { for(int j=1;j+(1<<(i))-1<=n;j++) { st[j][i]=max(st[j][i-1],st[j+(1<<(i-1))][i-1]); // cout<<st[j][i]<<" "; }//cout<<endl; } while(q--) { ask(); } }//1 2 3 4 5 }t; int main() { t.work(); return 0; }/* 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 */
並不對勁的st表