思路:
区间最值一定是相邻的差值的绝对值。
预处理差值绝对值,预处理以每个位置的值为最大值能延伸的最长距离(单调栈处理)。
然后每次询问就是枚举区间,计算每个值的贡献。
//#pragma comment(linker, "/STACK:102400000,102400000")
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define lson num<<1, Left, Mid
#define rson num<<1|1, Mid+1, Right
#define mem(a, b) memset(a, b, sizeof(a))
typedef pair<int,int> PII;
const double pi = acos(-1.0);
const double eps = 1e-6;
const LL Mod = 1e9 + 7;
const int Maxn = 2e5 + 10;
struct asd{
int id;
LL Left, Right, w;
};
stack<asd>st;
LL a[Maxn];
LL ans[Maxn][2];
int n, q;
LL ABS(LL x){
if(x < 0) x = -x;
return x;
}
void init(){
for(int i=1;i<n;i++)
a[i] = ABS(a[i] - a[i+1]);
asd now, nex;
now.id = 1;
now.Left = now.Right = 1;
now.w = a[1];
st.push(now);
for(int i=2;i<n;i++){
nex.id = i;
nex.Left = nex.Right = i;
nex.w = a[i];
while(!st.empty() && st.top().w < a[i]){
now = st.top();st.pop();
ans[now.id][0] = now.Left;
ans[now.id][1] = now.Right;
if(!st.empty()) st.top().Right = now.Right;
nex.Left = now.Left;
}
st.push(nex);
}
while(!st.empty()){
now = st.top();st.pop();
ans[now.id][0] = now.Left;
ans[now.id][1] = now.Right;
if(!st.empty()) st.top().Right = now.Right;
}
}
LL solve(LL Left, LL Right){
LL L, R;
LL res = 0;
for(int i=Left;i<Right;i++){
L = max(Left, ans[i][0]);
R = min(Right-1, ans[i][1]);
res = res + a[i]*(i-L+1)*(R-i+1);
}
return res;
}
int main(){
LL L, R;
scanf("%d%d", &n, &q);
for(int i=1;i<=n;i++) scanf("%I64d", &a[i]);
init();
for(int i=1;i<=q;i++){
scanf("%I64d%I64d", &L, &R);
printf("%I64d\n",solve(L, R));
}
return 0;
}