Solution
每次遇到这种比较复杂的问题的时候,可以先从比较直观的暴力方法去考虑再去思考如何优化。
比如这道题,我们比较容易的想到的是的dp转移。
定义:
: 到第
个建筑物的最大美丽值。
:
到
之间最矮的建筑物的美丽值,即
。
为了降低复杂度,DP存在很多种优化方式,而这道题需要用到单调队列优化。
仔细观察,我们可以发现 是单调递增的,
是固定的。
利用单调栈维护单调递减的 数组对应的下标,对于
, 我们可以找到左侧最近的
, 使得
,此时
有两种可能:
- 将
和
放入到一张照片,此时答案为
- 将
放入到一张照片,
O(NlogN)
#include <bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define lowbit(x) ((x) & -(x))
using namespace std;
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
constexpr double eps = 1e-8;
constexpr int NINF = 0xc0c0c0c0;
constexpr int INF = 0x3f3f3f3f;
constexpr ll LINF = 0x3f3f3f3f3f3f3f3f;
constexpr ll LNINF = 0xc0c0c0c0c0c0c0c0;
constexpr ll mod = 1e9 + 7;
constexpr ll N = 3e5 + 5;
int n, h[N], b[N], l[N];
ll f[N];
#define ls (p << 1)
#define rs (ls | 1)
#define tm ((tl + tr) >> 1)
ll mx[N << 2];
void up(int p) {
mx[p] = max(mx[ls], mx[rs]);
}
void modify(int p, int tl, int tr, int pos, ll v) {
if (tl == tr) {
mx[p] = v;
} else {
if (tm >= pos) modify(ls, tl, tm, pos, v);
else modify(rs, tm + 1, tr, pos, v);
up(p);
}
}
ll query(int p, int tl, int tr, int l, int r) {
if (r < l) {
return 0;
} else if (l <= tl && tr <= r) {
return mx[p];
} else {
ll ans = LLONG_MIN;
if (tm >= l) ans = max(ans, query(ls, tl, tm, l, r));
if (tm < r) ans = max(ans, query(rs, tm + 1, tr, l, r));
return ans;
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n;
for (int i = 1; i <= n; i++) cin >> h[i];
for (int i = 1; i <= n; i++) cin >> b[i];
vector<int> stk;
for (int i = 1; i <= n; i++) {
while (!stk.empty() && h[stk.back()] > h[i]) {
stk.pop_back();
}
if (!stk.empty()) l[i] = stk.back();
stk.push_back(i);
}
memset(mx, sizeof(mx), 0xc0);
f[0] = LNINF;
modify(1, 0, n, 0, 0);
for (int i = 1; i <= n; i++) {
f[i] = max(f[l[i]], query(1, 0, n, l[i], i - 1) + b[i]);
modify(1, 0, n, i, f[i]);
}
cout << f[n] << '\n';
return 0;
}Code O(NlogN)
#include <bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define lowbit(x) ((x) & -(x))
using namespace std;
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
constexpr double eps = 1e-8;
constexpr int NINF = 0xc0c0c0c0;
constexpr int INF = 0x3f3f3f3f;
constexpr ll mod = 1e9 + 7;
constexpr ll N = 1e6 + 5;
int n, h[N], b[N], stk[N];
ll stk_v[N], f[N];
bool in_queue[N];
priority_queue<pair<ll, int>> pq;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n;
for (int i = 1; i <= n; i++) cin >> h[i];
for (int i = 1; i <= n; i++) cin >> b[i];
int top = 0;
for (int i = 1; i <= n; i++) {
ll now = f[i - 1];
while (top > 0 && h[i] < h[stk[top]]) {
now = max(now, stk_v[top]);
in_queue[stk[top]] = false;
top--;
}
stk[++top] = i;
stk_v[top] = now;
in_queue[i] = true;
pq.push(make_pair(now + b[i], i));
while (!in_queue[pq.top().second]) pq.pop();
f[i] = pq.top().first;
}
cout << f[n] << '\n';
return 0;
}O(N)
#include <bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define ls (p << 1)
#define rs (ls | 1)
#define tm ((tl + tr) >> 1)
#define lowbit(x) ((x) & -(x))
using namespace std;
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
constexpr double eps = 1e-8;
constexpr int NINF = 0xc0c0c0c0;
constexpr int INF = 0x3f3f3f3f;
constexpr ll LNINF = 0xc0c0c0c0c0c0c0c0;
constexpr ll LINF = 0x3f3f3f3f3f3f3f3f;
constexpr ll mod = 1e9 + 7;
constexpr ll N = 1e6 + 5;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<int> h(n), b(n);
for (auto &i : h) cin >> i;
for (auto &i : b) cin >> i;
vector<ll> f(n);
stack<int> stk;
stack<ll> stkdp, stkmax;
for (int i = 0; i < n; i++) {
ll mx = i == 0 ? 0 : f[i - 1];
while (!stk.empty() && h[stk.top()] > h[i]) {
mx = max(mx, stkdp.top());
stk.pop();
stkdp.pop();
stkmax.pop();
}
stkdp.push(mx);
if (stkmax.empty()) {
stkmax.push(mx + b[i]);
} else {
stkmax.push(max(stkmax.top(), mx + b[i]));
}
f[i] = stkmax.top();
stk.push(i);
}
cout << f[n - 1] << '\n';
return 0;
}
京公网安备 11010502036488号