我又来发一篇题解啦
其实这一题只是一道板子题,但因为我对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
#includeusing 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< ) for(int i=1;i+(1< 1<=n;i++)//循环顺序一定不能变,要先算出长度为2^(j-1)才能算2^j的 { f_min[i][j]=min(f_min[i][j-1],f_min[i+(1< 1)][j-1]); f_max[i][j]=max(f_max[i][j-1],f_max[i+(1< 1)][j-1]); } for(int i=1;i<=m;i++) { int x,y; cin>>x>>y; int s=logg[y-x+1]; cout< 1< 1][s])-min(f_min[x][s],f_min[y-(1<1][s])<<endl; } }