[ HNOI2016 ] 序列
题目
思路
代码
#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;
}