HDU 1506 / SP1805 Largest Rectangle in a Histogram
题目
思路
我们要充分利用笛卡尔树的性质:
- 一颗子树内的点表现在数组上都是连续的;
- 一颗子树内的点的大小都大于等于子树跟的数值大小。
所以我们建出笛卡尔树,用 dfs 求出以每个点为子树的子树大小 \(sz_i\),那么对于这个高度 \(h_i\) 来说,其子节点的高度比它大,所以可以拓展开来,面积为 \(sz_i \cdot h_i\),最后取个 max 即可。
代码
// hdu 1506
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
const int N = 100010;
int n, a[N];
int lc[N], rc[N];
int stk[N], top;
int sz[N];
void dfs(int u) {
sz[u] = 1;
if (lc[u]) dfs(lc[u]);
if (rc[u]) dfs(rc[u]);
sz[u] += sz[lc[u]] + sz[rc[u]];
}
void solve() {
fill(lc + 1, lc + n + 1, 0);
fill(rc + 1, rc + n + 1, 0);
top = 0;
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= n; i++) {
int k = top;
while (k && a[stk[k]] > a[i]) k--;
if (k) rc[stk[k]] = i;
if (k < top) lc[i] = stk[k + 1];
stk[++k] = i;
top = k;
}
dfs(stk[1]);
i64 ans = 0;
for (int i = 1; i <= n; i++) ans = max(ans, 1ll * sz[i] * a[i]);
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
while (cin >> n && n) solve();
return 0;
}