新做了两道题居然和之前套路是一样的,就不重复了
有趣的是
while (!s.empty() && a[s.top()] < a[i]) 这个循环里,< 和 <=这两个都可以,模拟了一下发现,当你想把一个数字入栈的时候,如果前面一个数字和当前这个一样,虽然当前这个数字不能向前搜到最深,但是前一个数字和这个是一样的,所以一定有一个能向前找到最深的和当前这个数字相同的数字。
POJ-2796
#include <cstdio> #include <algorithm> #include <stack> using namespace std; const int N = 100010; int a[N]; typedef long long ll; ll pre[N]; stack < int > s; int main() { int n, l = 1, r = 1; scanf("%d", &n); for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); pre[i] = pre[i - 1] + a[i]; } ll ans = 0; for (int i = 1; i <= n; i++) { int top = i; while (!s.empty() && a[s.top()] > a[i]) { top = s.top(); if (ans < 1ll * (pre[i - 1] - pre[top - 1]) * a[top]) { ans = 1ll * (pre[i - 1] - pre[top - 1]) * a[top]; l = s.top(); r = i - 1; } s.pop(); } a[top] = a[i]; s.push(top); } while (!s.empty()) { if (ans < 1ll * (pre[n] - pre[s.top() - 1]) * a[s.top()]) { ans = 1ll * (pre[n] - pre[s.top() - 1]) * a[s.top()]; l = s.top(); r = n; } s.pop(); } printf("%lld %d %d", ans, l, r); return 0; }
POJ-2559
#include <cstdio> #include <algorithm> #include <stack> using namespace std; stack < int > s; typedef long long ll; const int N = 100010; ll h[N]; int main() { int n; while (~scanf("%d", &n)) { if (n == 0) break; ll ans = 0; for (int i = 0; i < n; i++) { scanf("%lld", &h[i]); int top = i; while (!s.empty() && h[s.top()] > h[i]) { top = s.top(); s.pop(); ans = max(ans, 1ll * (i - top) * h[top]); } h[top] = h[i]; s.push(top); } while (!s.empty()) { ans = max(ans, 1ll * (n - s.top()) * h[s.top()]); s.pop(); } printf("%lld ", ans); } return 0; }
笛卡尔树就放到RMQ的时候一起学吧