RMQ 区间最值 模板

来源:互联网 发布:机甲风暴java破解版 编辑:程序博客网 时间:2024/05/22 02:28
  1. RMQ 的全称为Range Max/Min Query。
  2. 构造dp数组的时间为O(nlogn), 但是查询时间为O(1),所以当数据量小于logn时,用朴素遍历找最值就好,但是请求次数大于logn时,就要用这个模板。
  3. 利用动态规划的思想。
int order[maxn];//使每一个2^order[i] <= i <= 2^(order[i]+1)void init_order(int n){    order[0] = -1;    for(int i = 1; i <= n; ++i)        order[i] = ((i&(i-1))==0) ? order[i-1]+1 : order[i-1];}//求值//2^20 > maxn,动态规划,保存最优值int dp_min[maxn][20];void init_RMQ_min(int n, int v[]){//需要先执行init_order    for(int i = 0; i < n; ++i)        dp_min[i][0] = v[i];    for(int i = 1; i <= order[n]; ++i)        for(int j = 0; j < n+1-(1<<i); ++j)            dp_min[j][i] = min(dp_min[j][i-1], dp_min[j+(1<<(i-1))][i-1]);}int ask_RMQ_min(int l, int r){//r >= l    int k = order[r-l+1];    return min(dp_min[l][k], dp_min[r-(1<<k)+1][k]);}int dp_max[maxn][20];void init_RMQ_max(int n, int v[]){//需要先执行init_order    for(int i = 0; i < n; ++i)        dp_max[i][0] = v[i];    for(int i = 1; i <= order[n]; ++i)        for(int j = 0; j < n+1-(1<<i); ++j)            dp_max[j][i] = max(dp_max[j][i-1], dp_max[j+(1<<(i-1))][i-1]);}int ask_RMQ_max(int l, int r){//r >= l    int k = order[r-l+1];    return max(dp_max[l][k], dp_max[r-(1<<k)+1][k]);}//求下标int dp_min_idx[maxn][20];void init_RMQ_min_idx(int n, int v[]){//需要先执行init_order    for(int i = 0; i < n; ++i)        dp_min_idx[i][0] = i;    for(int i = 1; i <= order[n]; ++i)        for(int j = 0; j < n+1-(1<<i); ++j)            dp_min_idx[j][i] = v[dp_min_idx[j][i-1]] < v[dp_min_idx[j+(1<<(i-1))][i-1]] ? dp_min_idx[j][i-1] : dp_min_idx[j+(1<<(i-1))][i-1];}int ask_RMQ_min_idx(int l, int r, int v[]){//r >= l    int k = order[r-l+1];    return v[dp_min_idx[l][k]] < v[dp_min_idx[r-(1<<k)+1][k]] ? dp_min_idx[l][k] : dp_min_idx[r-(1<<k)+1][k];}int dp_max_idx[maxn][20];void init_RMQ_max_idx(int n, int v[]){//需要先执行init_order    for(int i = 0; i < n; ++i)        dp_max_idx[i][0] = i;    for(int i = 1; i <= order[n]; ++i)        for(int j = 0; j < n+1-(1<<i); ++j)            dp_max_idx[j][i] = v[dp_max_idx[j][i-1]] > v[dp_max_idx[j+(1<<(i-1))][i-1]] ? dp_max_idx[j][i-1] : dp_max_idx[j+(1<<(i-1))][i-1];}int ask_RMQ_max_idx(int l, int r, int v[]){//r >= l    int k = order[r-l+1];    return v[dp_max_idx[l][k]] > v[dp_max_idx[r-(1<<k)+1][k]] ? dp_max_idx[l][k] : dp_max_idx[r-(1<<k)+1][k];}
1 0
原创粉丝点击