D - Lipshitz Sequence CodeForces - 602D(单调栈+思维)

题目链接http://codeforces.com/problemset/problem/602/D

A function  is called Lipschitz continuous if there is a real constant K such that the inequality |f(x) - f(y)| ≤ K·|x - y| holds for all . We'll deal with a more... discrete version of this term.

For an array , we define it's Lipschitz constant  as follows:

  • if n < 2, 
  • if n ≥ 2,  over all 1 ≤ i < j ≤ n

In other words,  is the smallest non-negative integer such that |h[i] - h[j]| ≤ L·|i - j| holds for all 1 ≤ i, j ≤ n.

You are given an array  of size n and q queries of the form [l, r]. For each query, consider the subarray ; determine the sum of Lipschitz constants of all subarrays of .

Input

The first line of the input contains two space-separated integers n and q (2 ≤ n ≤ 100 000 and 1 ≤ q ≤ 100) — the number of elements in array  and the number of queries respectively.

The second line contains n space-separated integers  ().

The following q lines describe queries. The i-th of those lines contains two space-separated integers li and ri (1 ≤ li < ri ≤ n).

Output

Print the answers to all queries in the order in which they are given in the input. For the i-th query, print one line containing a single integer — the sum of Lipschitz constants of all subarrays of .

Examples

Input
10 4
1 5 2 9 1 3 4 2 1 7
2 4
3 8
7 10
1 9
Output
17
82
23
210
Input
7 6
5 7 7 4 6 6 2
1 2
2 3
2 6
1 7
4 7
3 5
Output
2
0
22
59
16
8

Note

In the first query of the first sample, the Lipschitz constants of subarrays of  with length at least 2 are:

The answer to the query is their sum.

题目大意:

给你n个数字;
然后给你q个区间
每个区间l,r
让你求出[l,r]这个区间里面的数字的所有子列的L(h)的值的和;
(L(h)是任意两个点的斜率的绝对值的最大值);

思路:要求解这道题的关键是怎么快速求出一个区间里的斜率最大值会出现在哪,稍加分析,可以发现一个很重要的点,一个区间里斜率最大的时候只会出现在

相邻的两个数之间,这是解这道题的关键,可以看一下证明:

可以看下图;
这里写图片描述
假设斜率的最大值不在相邻的两点之间得到;
设中间还有一个k;
则如果ak大于ai,则ai,ak连起来肯定更优,肯定比ai,aj连起来的斜率大
如果ak小于ai的话,则是ak,aj连起来更优;
总之只有在i,j相邻的时候,斜率才可能取到最大;

此时我们得到了一个新的数组,就是相邻的两个数相减的绝对值,假设新的数组是b[i],现在我们只需要求得哪些区间包含b[i],并且b[i]是最大的,类似

算b[i]的贡献度,要找到b[i]能对多少个区间有贡献,其实就是往左走和往右走,最远能走多远,左边选一个数,右边选一个数,凑成一个区间就行了 

还有一种情况就是考虑相等的情况,任意一边考虑可以相等就行了,看代码:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cstdio>
#include<stack>
using namespace std;
typedef long long LL;
#define lson rt<<1
#define rson rt<<1|1
const int maxn=1e5+5;
const int maxm=50;
const int INF=1e9+7;
LL a[maxn],b[maxn];
LL l[maxn],r[maxn];
int main()
{
    LL N,Q;scanf("%lld%lld",&N,&Q);
    for(LL i=1;i<=N;i++)
    {
        scanf("%lld",&a[i]);
    }
    for(LL i=1;i<=Q;i++)
    {
        LL L,R;scanf("%lld%lld",&L,&R);
        LL p=1;
        for(LL j=L;j<R;j++)
        {
            b[p++]=abs(a[j+1]-a[j]);
        }
        stack<LL>st;
        for(LL j=1;j<p;j++)
        {
            if(st.empty())
            {
                l[j]=0;
                st.push(j);
            }
            else//维护栈中数据单调递减
            {
                while(!st.empty()&&b[st.top()]<b[j]) st.pop();
                if(st.empty()) l[j]=0;
                else l[j]=st.top();
                st.push(j);
            }
        }
        stack<LL>st1;
        for(LL j=p-1;j>=1;j--)
        {
            if(st1.empty())
            {
                r[j]=p;
                st1.push(j);
            }
            else//维护栈中数据单调递减
            {
                while(!st1.empty()&&b[st1.top()]<=b[j]) st1.pop();
                if(st1.empty()) r[j]=p;
                else r[j]=st1.top();
                st1.push(j);
            }
        }
        LL ans=0;
        for(LL j=1;j<p;j++)
        {
            ans+=b[j]*(j-l[j])*(r[j]-j);
        }
        printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/caijiaming/p/12005265.html