题目:
分析:
为什么要倍增?一方面是节省数组,另一方面状态转移的也快了,因为需要的状态都少了,
不倍增时,f【2,8】=max(f【2,7】,A【2+8】)。
2的多少次方应该想到移位运算的啊!
先看ac代码的结构:
其相当于独立的n个问题进行的求解,即使两次数据相同,也要再重新完完全全的算一遍。不是,是先算出来几乎全部,具体情况再处理。
很明显的一个递推,自己非要写成递归。
当具体问题时,我想的利用2的次方的性质,从大向小加,因为2的次方总能拼成任何的数字。具体为:
而题解这样不是更简单吗?
有重复无所谓呀,自己还是太菜。
全抄代码:
#include<bits/stdc++.h>
using namespace std;
int A1[50005][20];
int A2[50005][20];
int A[50005];
void work1(int n)
{
for ( int i=1;i<=n;i++) A1[i][0]=A[i];
for (int j=1;(1<<j)<=n;j++)
for (int i=1;i+(1<<j)-1<=n;i++)
A1[i][j]=max(A1[i][j-1],A1[i+(1<<(j-1))][j - 1]);
}
void work2(int n)
{
for (int i=1;i<=n;i++) A2[i][0]=A[i];
for (int j=1;(1<<j)<=n;j++)
for (int i=1;i+(1<<j)-1<=n;i++)
A2[i][j]=min(A2[i][j-1],A2[i+(1<<(j-1))][j - 1]);
}
int RMQ(int l, int r)
{
int k=0;
while ((1<<(k+1))<=r-l+1)
k++;
return max(A1[l][k],A1[r-(1<<k)+1][k]);
}
int RMQ2(int l, int r)
{
int k=0;
while ((1<<(k+1))<=r-l+1)
k++;
return min(A2[l][k],A2[r-(1<<k)+1][k]);
}
int main()
{
int m,n;
cin>>m>>n;
for(int i=1;i<=m;i++) cin>>A[i];
work1(m);
work2(m);
for(int ii=0;ii<n;ii++)
{
int x,y;
cin>>x>>y;
cout<<RMQ(x,y)-RMQ2(x,y)<<endl;
}
}