【分析】
倍增算法 or 线段树。
笔者使用倍增算法。
扩充倍增算法,记录pre[K][N],mn[K][N],mx[K][N],l_r[K][N],r_l[K][N],分别保存对应节点,最小值,最大值,从左到右的答案,从右到左的答案。
首先奠定基础,pre[0][i]=max(i+1,n),mn[0][i]=min(value[i],value[pre[0][i]]),mx同理,l_r[0][i]=max(0,value[pre[0][i]]-value[i]),r_l同理。
然后转移,pre[i][j]=pre[i-1][pre[i-1][j]],mx[i][j]=max(mx[i-1][j],mx[i-1][pre[i-1][j]]),l_r[i][j]=max(l_r[i-1][j],l_r[i-1][pre[i-1][j]],mx[i-1][pre[i-1][j]]-mn[i-1][j]),r_l同理。
倍增预处理完成,接着查询。
分类讨论,若l<=r则从左往右跳,取当前区间值l_r和区间相差值的最大值,r<=l同理
【代码】
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
using namespace std;
const int N=200001;
const int K=20;
const int M=300000000;
int n,m,value[N]; //Basic
int pre[K][N],mx[K][N],mn[K][N],l_r[K][N],r_l[K][N],unit; //Double
inline int min(int i,int j)
{
return i<j?i:j;
}
inline int max(int i,int j)
{
return i>j?i:j;
}
void init(void)
{
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d",&value[i]);
for (int i=1;i<n;i++) pre[0][i]=i+1;
pre[0][n]=n;
for (int i=1;i<=n;i++)
{
mx[0][i]=max(value[i],value[pre[0][i]]);
mn[0][i]=min(value[i],value[pre[0][i]]);
l_r[0][i]=value[pre[0][i]]-value[i];
r_l[0][i]=value[i]-value[pre[0][i]];
}
unit=log(n)/log(2);
for (int i=1;i<=unit;i++)
for (int j=1;j<=n;j++)
{
pre[i][j]=pre[i-1][pre[i-1][j]];
mx[i][j]=max(mx[i-1][j],mx[i-1][pre[i-1][j]]);
mn[i][j]=min(mn[i-1][j],mn[i-1][pre[i-1][j]]);
l_r[i][j]=max(l_r[i-1][j],l_r[i-1][pre[i-1][j]]);
l_r[i][j]=max(l_r[i][j],mx[i-1][pre[i-1][j]]-mn[i-1][j]);
r_l[i][j]=max(r_l[i-1][j],r_l[i-1][pre[i-1][j]]);
r_l[i][j]=max(r_l[i][j],mx[i-1][j]-mn[i-1][pre[i-1][j]]);
}
}
inline int query(int l,int r)
{
int res=0;
if (l<=r)
{
int lrgo=M;
for (int i=unit;i+1;i--)
if (pre[i][l]<=r)
{
res=max(res,l_r[i][l]);
res=max(res,mx[i][l]-lrgo);
lrgo=min(lrgo,mn[i][l]);
if ((l=pre[i][l])==r) break;
}
}
else
{
int rlgo=0;
l^=r^=l^=r;
for (int i=unit;i+1;i--)
if (pre[i][l]<=r)
{
res=max(res,r_l[i][l]);
res=max(res,rlgo-mn[i][l]);
rlgo=max(rlgo,mx[i][l]);
if ((l=pre[i][l])==r) break;
}
}
return res;
}
void work(void)
{
int x,y;
scanf("%d",&m);
for (;m--;)
{
scanf("%d%d",&x,&y);
printf("%d\n",query(x,y));
}
}
int main(void)
{
init();
work();
return 0;
}原文地址:http://blog.csdn.net/u013598409/article/details/45441049