B. Lipshitz Sequence
Time Limit: 20 Sec
Memory Limit: 256 MB
题目连接
http://codeforces.com/contest/601/problem/B
Description
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 .
Sample Input
10 4
1 5 2 9 1 3 4 2 1 7
2 4
3 8
7 10
1 9
Sample Output
17
82
23
210
HINT
题意
给你n个数,Q次询问,问你区间l,r区间里面的 区间斜率最大值 的区间和 是多少
题解:
比较绕。。。
首先斜率最大值一定是相邻的,这个可以很容易通过画图来解决
然后我们就用st表+二分来找到第一个比他大的数在哪儿就好了~
然后就可以跑一遍就行了
代码:
#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
#define maxn 100005
int n;
int dp[maxn][];
int dp1[maxn][];
int A[maxn];
int a[maxn];
int L[maxn],R[maxn];
int mm[maxn];
void initrmp(int n)
{
mm[]=-;
for(int i=;i<=n;i++)
{
mm[i]=((i&(i-))==)?mm[i-]+:mm[i-];
dp[i][]=a[i];
dp1[i][]=a[i];
}
for(int j = ;j<=mm[n];j++)
for(int i=;i+(<<j)-<=n;i++)
dp[i][j]=max(dp[i][j-],dp[i+(<<(j-))][j-]);
for(int j = ;j<=mm[n];j++)
for(int i=;i+(<<j)-<=n;i++)
dp1[i][j]=min(dp1[i][j-],dp1[i+(<<(j-))][j-]);
}
int queryMax(int l,int r)
{
int k = mm[r-l+];
return max(dp[l][k],dp[r-(<<k)+][k]);
}
int queryMin(int l,int r)
{
int k = mm[r-l+];
return min(dp1[l][k],dp1[r-(<<k)+][k]);
}
int main()
{
scanf("%d",&n);
int q;scanf("%d",&q);
for(int i=;i<=n;i++)
scanf("%d",&A[i]);
n--;
for(int i=;i<=n;i++)
a[i]=abs(A[i+]-A[i]);
int Ans = ;
initrmp(n);
for(int i=;i<=n;i++)
{
int l=,r=i;
while(l<=r)
{
int mid = (l+r)/;
if(queryMax(mid,i-)<a[i])r=mid-;
else l=mid+;
}
L[i]=l;
l=i,r=n;
while(l<=r)
{
int mid = (l+r)/;
if(queryMax(i+,mid)<=a[i])l=mid+;
else r=mid-;
}
R[i]=l-;
} for(int i=;i<=q;i++)
{
int x,y;scanf("%d%d",&x,&y);
y--;
long long Ans = ;
for(int j=x;j<=y;j++)
Ans += 1LL*(j-max(L[j],x)+)*(min(R[j],y)-j+)*a[j];
printf("%lld\n",Ans);
}
}