-------------------------------------算法简述----------------------------------------- ST算法O(nlogn)预处理,O(1)的查询指定区间的最值(以最小值为例) 基本上是把待求区间[l,r]分为两段长为len的区间 左边一段为[l,l+len-1],右边一段为[r-len+1,r] len必须使得两段区间覆盖待求区间 设所求数组为w 那么,所求最小值就是两个区间的最小值间的最小值 即min(min{w[i],l<=i<=l+len-1},min{w[j],r-len+1<=j<=r}) 若都在预先处理中先求得两个区间的最小值 则每次查询的复杂度都是O(1) ---
对len做一个限制:只能为2的幂 在预处理中求出所有mi[b][t] : 以b为起点,长为2^t的区间的最小值. 则求解min(min{w[i],l<=i<=l+len-1},min{w[j],r-len+1<=j<=r}) 就变成min(mi[l][t],mi[r-2^t+1][r]),其中t可以由此得出,以保证两段区间可以覆盖待求区间: t=ln(r-l+1)/ln(2) ---
可以看到mi[b][t]=min(mi[b][t-1],mi[b+2^(t-1)-1][t-1]) 特别地对于所有mi[i][0],其值都是w[i]; 由此自底向上推出所有的mi[b][t] mi大小为n*logn,预处理时间复杂度为O(nlogn),查询时间复杂度为O(1) -----------------------------------------------------代码------------------------------------------------------ 在POJ上测试, 反应良好~ 不知道怎么样把函数指针指向任意类型的<操作符, 只能总是提供一个"小于"函数 查询指定区间的最小值. ----------------------------------以下是模板------------------------------------- template < class Type> int dint(double a){ int mlen(int l,int r){ public:
int query_index(int l,int r);//返回指定区间最小值的元素索引 Type query(int l,int r);//返回指定区间的最小元素 template < class Type> template < class Type> template < class Type> template < class Type> template < class Type> /*----------------Example : POJ 3264 Memory:7708K Time:3230MS-----------------*/ int cow[50001]; bool cmpmin(int& t1,int& t2){ bool cmpmax(int& t1,int& t2){ int main() |
转载于:https://www.cnblogs.com/ACAC/archive/2010/05/24/1743142.html