题目
输入样例
12
0 1 0 2 1 0 1 3 2 1 2 1
输出样例
6
解题思路
可以发现最后能拦住水的都是向两边递减高度(?)
不管两个高积木之间的的积木是怎样乱七八糟的高度,最后能用来装水的还是那两个积木
先找到最高的那个积木,从中间向两边分别做单调栈
距离乘高很容易,怎么减去中间的积木体积?
!前缀和
Code
#include <bits/stdc++.h>
#define ll long long
#define N 50000
using namespace std;
ll n, ans, top, max_num, max_id, a[N + 100], s[N + 100], q[N + 100];
int main() {
scanf("%lld", &n);
for(int i = 1; i <= n; i ++) {
scanf("%lld", &a[i]);
s[i] = s[i - 1] + a[i]; //前缀和
if(a[i] > max_num) { //找最高的积木
max_num =a[i];
max_id = i;
}
}
q[++ top] = max_id; //左边
for(int i = max_id - 1; i; i --) {
while(top && a[q[top]] < a[i]) top --;
q[++ top] = i;
}
while(top > 1) {
ans += a[q[top]] * (q[top - 1] - q[top] - 1) - (s[q[top - 1] - 1] - s[q[top]]);
top --;
}
//***************************************************
for(int i = max_id + 1; i <= n; i ++) { //右边
while(top && a[q[top]] < a[i]) top --;
q[++ top] = i;
}
while(top > 1) {
ans += a[q[top]] * (q[top] - q[top - 1] - 1) - (s[q[top] - 1] - s[q[top - 1]]);
top --;
}
printf("%lld", ans);
}