ST算法
用dp[i][j]来表示以i为起点2^j的长度范围内的最值
初始化时,dp[i][0]就是数本身,而递推,显然,dp[i][j]可以用dp[i][j-1]
和dp[i+(1<<(j-1))][j-1]
来得出
而在查询的时候,因为一个dp表示2^n的范围,所以不管什么区间都可以用至多两个dp来得出
比如1~7就可以用dp[1][2](1~4)和 dp[4][2](4~7)比较得出
公式:
dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1])
L=(int)(log(r-l+1.0)/log(2.0))
ans(l,r)=max(dp[l][L],dp[r-(1<<L)+1][L])
虽然ST很快,但为什么很多时候用线段树或者树状数组而不是ST呢?因为它不具备更新的能力
题意:
给数组,每次询问求区间最大值减最小值
代码:
D read(){ D ans=0; char last=' ',ch=getchar();
while(ch<'0' || ch>'9')last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans; return ans;
}
int ma[50009][30],mi[50009][30];
int main(){
int n=read(),q=read();
for(int i=1;i<=n;i++)ma[i][0]=read(),mi[i][0]=ma[i][0];
int L=(int)(log(1.0*n)/log(2.0));
for(int j=1;j<=L;j++){
for(int i=1;i<n;i++){
if(i-1+(1<<j)>n)break;
mi[i][j]=min(mi[i][j-1],mi[i+(1<<(j-1))][j-1]);
ma[i][j]=max(ma[i][j-1],ma[i+(1<<(j-1))][j-1]);
}
}
while(q--){
int l=read(),r=read();
int L=(int)(log(r-l+1.0)/log(2.0));
int ans=max(ma[l][L],ma[r-(1<<L)+1][L]);
ans-=min(mi[l][L],mi[r-(1<<L)+1][L]);
printf("%d\n",ans);
}
}