【分析】
倍增算法 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