分析:很容易想到,区间斜率绝对值的最大值一定是所有相邻的斜率中的最大值。
然后把序列处理成后一个数减前一个数的绝对值。
由于
q
非常小,所以每一次询问支持
找左边第一个比该数大的值可以通过单调队列来搞定,预处理出所有的 ,L,R 。这题总的复杂度: o(nlogn+qn)
附上代码:
#include <bits/stdc++.h>
#define LL long long
#define FOR(i,x,y) for(int i = x;i < y;++ i)
#define IFOR(i,x,y) for(int i = x;i > y;-- i)
using namespace std;
typedef pair<int,int> pii;
const int maxn = 100010;
const int inf = 1<<30;
int L[maxn],R[maxn];
int q[maxn],head,a[maxn];
pii dif[maxn];
int n,m;
void init(){
IFOR(i,n-1,0) a[i] = abs(a[i]-a[i-1]),dif[i] = make_pair(a[i],i);
dif[0] = make_pair(inf,0);
head = 0;
q[head++] = 0;
FOR(i,1,n){
while(a[i] >= dif[q[head-1]].first)
-- head;
L[i] = dif[q[head-1]].second;
q[head++] = i;
}
dif[n] = make_pair(inf,n);
head = 0;
q[head++] = n;
IFOR(i,n-1,0){
while(a[i] > dif[q[head-1]].first) -- head;
R[i] = dif[q[head-1]].second;
q[head++] = i;
}
}
void work(){
FOR(i,0,m){
int l,r;
scanf("%d%d",&l,&r);
-- l; -- r;
LL ans = 0;
FOR(i,l+1,r+1){
LL llen = i - max(L[i],l),rlen = min(R[i],r+1) - i;
ans += llen*rlen*a[i];
}
printf("%I64d\n",ans);
}
}
int main()
{
//freopen("test.in","r",stdin);
while(~scanf("%d%d",&n,&m)){
FOR(i,0,n) scanf("%d",&a[i]);
init();
work();
}
return 0;
}