$[Luogu]$ 洛谷 $P2880$ 题解【[USACO07JAN]平衡的阵容Balanced Lineup】

我又来发一篇题解啦

其实这一题只是一道板子题,但因为我对RMQ又有些不记得了

所以发篇题解加深印象

直入正题

核心思想是DP+倍增

不妨我们先来看一个1,2,3,4,……2^n的例子

它的最大值一定是1~2^(n-1)的max与2^(n-1)+1的max的max

这样我们每次算下去就可以很快地得出答案

那么问题来了,如果我们询问的区间不是长度为2^n的呢?

不妨假设它的长度为l,令s=floor(log(l))(以下的log底数为2)

则它的最大值一定是从头取2^s个的这一段区间的max与从尾取2^s个的这一段区间的max(两者会有重叠的部分,不过不影响)

如此,这一题就搞完啦QAQ

#include<bits/stdc++.h>
using namespace std;
int n,m;
int a[50001];
int logg[50001];
int f_min[50001][20],f_max[50001][20];
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++)
      cin>>a[i];
    logg[0]=-1;
    for(int i=1;i<=n;i++)
      f_min[i][0]=a[i],f_max[i][0]=a[i],logg[i]=logg[i>>1]+1;
    for(int j=1;(1<<j)<=n;j++)
      for(int i=1;i+(1<<j)-1<=n;i++)//循环顺序一定不能变,要先算出长度为2^(j-1)才能算2^j的
      {
        f_min[i][j]=min(f_min[i][j-1],f_min[i+(1<<j-1)][j-1]);
        f_max[i][j]=max(f_max[i][j-1],f_max[i+(1<<j-1)][j-1]);
      }
    for(int i=1;i<=m;i++)
    {
        int x,y;
        cin>>x>>y;
        int s=logg[y-x+1];
        cout<<max(f_max[x][s],f_max[y-(1<<s)+1][s])-min(f_min[x][s],f_min[y-(1<<s)+1][s])<<endl;
    }
}

 

posted @ 2018-10-14 19:20  风骨傲天  阅读(181)  评论(0编辑  收藏  举报