[ HNOI2016 ] 序列

题目

Luogu
LOJ
Acwing

思路

002.png 003.png

代码

#include <iostream>
#include <cstdio>
#include <cmath>
#define int long long
using namespace std;
const int N = 2000010;
int n, m, a[N], M[22][N], stk[N], top;
int pre[N], suf[N], fl[N], fr[N], gl[N], gr[N];
int RMQ(int l, int r) { 
    int k = log2(r - l + 1);
    int x = M[k][l], y = M[k][r - (1 << k) + 1];
    return (a[x] < a[y] ? x : y);
}
signed main() {
    scanf("%lld%lld", &n, &m);
    for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
    for (int i = 1; i <= n; i++) M[0][i] = i;
    for (int i = 1; i <= 21; i++)
        for (int j = 1; j <= n; j++) {
            int x = M[i - 1][j], y = M[i - 1][j + (1 << i - 1)];
            M[i][j] = (a[x] < a[y]) ? x : y;
        }
    for (int i = 1; i <= n; i++) {
        while (top && a[stk[top]] >= a[i]) top--;
        pre[i] = stk[top], stk[++top] = i;
    }
    top = 0;
    for (int i = n; i >= 1; i--) {
        while (top && a[stk[top]] >= a[i]) top--;
        suf[i] = stk[top], stk[++top] = i;
    }
    for (int i = 1; i <= n; i++) 
        fr[i] = fr[pre[i]] + a[i] * (i - pre[i]), 
        gr[i] = gr[i - 1] + fr[i];
    for (int i = n; i >= 1; i--)
        fl[i] = fl[suf[i]] + a[i] * (suf[i] - i),
        gl[i] = gl[i + 1] + fl[i];
    for (int l, r; m--; ) {
        scanf("%lld%lld", &l, &r);
        int p = RMQ(l, r);
        printf("%lld\n", (p - l + 1) * (r - p + 1) * a[p] + 
                        gr[r] - gr[p] - fr[p] * (r - p) + 
                        gl[l] - gl[p] - fl[p] * (p - l));
    }
    return 0;
}
posted @ 2021-07-07 19:34  Protein_lzl  阅读(46)  评论(0编辑  收藏  举报