CodeForces601D【单调栈维护最大值】

思路:
区间最值一定是相邻的差值的绝对值。

预处理差值绝对值,预处理以每个位置的值为最大值能延伸的最长距离(单调栈处理)。
然后每次询问就是枚举区间,计算每个值的贡献。

//#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;
}

猜你喜欢

转载自blog.csdn.net/keyboarderqq/article/details/78664741