洛谷P11261 [COTS 2018] 直方图 Histogram 题解 笛卡尔树+启发式合并
题目链接:https://www.luogu.com.cn/problem/P11261
解题思路:完全来自 OrinLoong 大佬的博客。
示例程序:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int maxn = 1e5 + 5;
int n, a[maxn], ls[maxn], rs[maxn], rt;
ll p, ans, sum[maxn];
void init() {
for (int i = 1; i <= n; i++)
sum[i] = sum[i-1] + (p - 1) / i;
}
void dfs(int u, int l, int r) {
if (!u)
return;
dfs(ls[u], l, u-1);
dfs(rs[u], u+1, r);
if (u - l < r - u) { // 枚举左边一段的长度(左端点)
for (int i = 0; i <= u-l; i++) {
int L = max(i+1ll, (p-1)/a[u]+1), R = r - u + 1 + i;
if (L <= R) {
ans += 1ll * (R - L + 1) * a[u] - (sum[R] - sum[L-1]);
}
}
}
else { // 枚举右边一段的长度(右端点)
for (int i = 0; i <= r-u; i++) {
int L = max(i+1ll, (p-1)/a[u]+1), R = u - l + 1 + i;
if (L <= R) {
ans += 1ll * (R - L + 1) * a[u] - (sum[R] - sum[L-1]);
}
}
}
}
void solve() {
stack<int> stk;
for (int i = 1; i <= n; i++) {
int last = 0;
while (!stk.empty() && a[stk.top()] > a[i]) {
last = stk.top();
stk.pop();
}
if (!stk.empty()) rs[stk.top()] = i;
else rt = i;
ls[i] = last;
stk.push(i);
}
dfs(rt, 1, n);
printf("%lld\n", ans);
}
int main() {
scanf("%d%lld", &n, &p);
for (int i = 1; i <= n; i++)
scanf("%d", a+i);
init();
solve();
return 0;
}
浙公网安备 33010602011771号