POJ - 3264 Balanced Lineup (ST表)
题意:给你一个长为N的序列,m次询问区间最大最小之差
思路:一开始用线段树做一直TLE,加速挂也开了,什么都写了还是TLE(可能是优化的还不够)。由于这道题不涉及任何的在线更新问题,于时就学到了一种 O(1)查询的 st表(RMQ基本算法)
其是利用递推以及倍增的思想,直接就离线处理好了区间最值。所以询问的时候直接O(1)就结束了
完整代码:
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <cmath> using namespace std; const int N=1e6+10; struct node{ int Max,Min; }st[N][21]; int query(int l,int r) { int k=log2(r-l+1);//深度 return max(st[l][k].Max,st[r-(1<<k)+1][k].Max)-min(st[l][k].Min,st[r-(1<<k)+1][k].Min); //记录的最底层 } int main() { int n,m; scanf("%d %d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&st[i][0].Max);//初始化 st[i][0].Min = st[i][0].Max; } for(int j=1;j<=20;j++){ for(int i=1;i+(1<<j)-1<=n;i++){ //利用倍增与递推的思想 st[i][j].Max=max(st[i][j-1].Max,st[i+(1<<(j-1))][j-1].Max); st[i][j].Min=min(st[i][j-1].Min,st[i+(1<<(j-1))][j-1].Min); } } while(m--){ int a,b; scanf("%d %d",&a,&b); printf("%d\n",query(a,b)); } return 0; }