视频加载失败

安吉D2-T2

1022 字
5 分钟
安吉D2-T2
原题呈现

P11261 直方图 Histogram#

题目描述#

给定笛卡尔坐标系中的直方图,宽度为 nn,第 ii 格的高度为 hih_i.也就是说,对于 1in\forall 1\le i\le n,第 ii 格所占矩形的顶点坐标分别为 (i1,0),(i,0),(i1,hi),(i,hi)(i-1,0),(i,0),(i-1,h_i),(i,h_i)

给定正整数 pp,求出满足以下条件的矩形的数量:

  • 矩形的四个顶点的坐标均为整数;
  • 矩形有一条边在 xx 轴上;
  • 矩形完全位于直方图内部(可以与边界相切);
  • 矩形的面积至少为 pp

输入格式#

第一行,两个正整数 n,pn,p

第二行,nn 个正整数 h1,h2,,hnh_1,h_2,\ldots,h_n

输出格式#

输出一行一个整数,表示答案.

输入输出样例 #1#

输入 #1#

6 9
1 4 4 5 2 3

输出 #1#

3

输入输出样例 #2#

输入 #2#

10 5
3 6 1 3 2 1 5 3 4 2

输出 #2#

31

说明/提示#

样例解释#

样例一解释:

数据范围#

对于 100%100\% 的数据,保证:

  • 1n1051\le n\le 10^5
  • 1p10141\le p\le 10^{14}
  • 1hi1091\le h_i\le 10^{9}
子任务编号nn\le pphih_i\le得分
1130003\, 0001012\le 10^{12}109 10^91010
2210510^5108\le 10^810001\, 0001515
33105 10^5=1=110910^91515
44105 10^5105\le 10^510910^925 25
55105 10^51014\le 10^{14}10910^93535

思路#

由于高度最小的一项是瓶颈,考虑以高度最小的一项为中点,先计算出左端点在中点左边,右端点在中点右边的方案数,再分治,分左半边和右半边两个子问题分别考虑.

在处理子问题 [l,r][l, r] 时,首先,使用 ST 表计算出 [l,r][l,r] 中最小的一项 limlim,其下表为 mm.若 mm 左边的元素数量更小,考虑枚举起点 ii,假定终点为 jj,则有方案数为:

i=lmj=rrmax{limpji+1+1,0}\sum^{m}_{i=l}\sum^{r}_{j=r}max\{lim - \lceil\frac{p}{j-i+1}\rceil + 1, 0\}

想想如何去掉 maxmax

limpji+1+10lim - \lceil\frac{p}{j-i+1}\rceil + 1 \geq 0 时,就有:

limpji+10limpji+1lim×(ji+1)pji+1plimjplim1+i\begin{align*} lim - \lceil\frac{p}{j-i+1}\rceil &\geq 0\\ lim &\geq\lceil\frac{p}{j-i+1}\rceil\\ lim \times(j - i + 1) &\geq p\\ j - i + 1 &\geq \frac{p}{lim}\\ j&\geq\frac{p}{lim} - 1 + i\\ \end{align*}

由于 jNj\in\mathbb{N},所以:

jplim1+ij\geq\lceil\frac{p}{lim}\rceil - 1 + i

令:need=plim1+ineed = \lceil\frac{p}{lim}\rceil - 1 + i

则原式化简为:

i=lmj=needr(limpji+1+1)i=lm(j=needr(lim+1)j=needr(pji+1))\begin{align*} \sum^{m}_{i=l}\sum^{r}_{j=need}(lim - \lceil\frac{p}{j-i+1}\rceil + 1)\\ \sum^{m}_{i=l}(\sum^{r}_{j=need}(lim + 1) - \sum^{r}_{j=need}(\lceil\frac{p}{j-i+1}\rceil)) \end{align*}

只需要使用前缀和记录 pi\lceil\frac{p}{i}\rceil,就可以在 O(n)O(n) 的时间里算出上式.

mm 右边的元素数量更小,也是同理,考虑枚举终点为 jj,假定起点为 ii,则若令 need=j+1plimneed = j + 1 - \lceil\frac{p}{lim}\rceil

原式化简为:

j=1m(i=lneed(lim+1)i=lneed(pji+1))\sum^{m}_{j=1}(\sum^{need}_{i=l}(lim + 1) - \sum^{need}_{i=l}(\lceil\frac{p}{j-i+1}\rceil))
#include <bits/stdc++.h>
#define int long long
using namespace std;
#define querySum(l, r) (sum[(r)] - sum[(l) - 1])
const int N = 1e5 + 100;
int n, p, h[N], sum[N], ans;
struct Node {
int n;
int id;
friend bool operator<(const Node a, const Node b) { return a.n < b.n; }
} st[N][20];
Node query(int l, int r) {
int len = log2(r - l + 1);
return min(st[l][len], st[r - (1 << (len)) + 1][len]);
}
int ceilDivided(int a, int b) {
double da = 1.0 * a / b;
int ia = a / b;
if (da != (double)ia) {
da++;
}
return da;
}
void solve(int l, int r) {
if (l > r) {
// 不可能存在合法方案
return;
}
if (l == r) {
// 仅一竖条
ans += max(0ll, h[l] - p + 1);
return;
}
int m = query(l, r).id;
int lim = h[m];
// 处理跨过中间的
if (m - l < r - m) {
// 左边更少一点
for (int i = l; i <= m; i++) {
int j0 = max(m, ceilDivided(p, lim) + i - 1);
if (j0 <= r)
ans +=
(lim + 1) * (r - j0 + 1) - querySum(j0 - i + 1, r - i + 1);
}
} else {
// 右边更少一点
for (int j = m; j <= r; j++) {
int i0 = min(m, j + 1 - ceilDivided(p, lim));
if (l <= i0)
ans +=
(lim + 1) * (i0 - l + 1) - querySum(j - i0 + 1, j - l + 1);
}
}
// 处理只在两边的
solve(l, m - 1);
solve(m + 1, r);
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n >> p;
// 预处理 ceil(p / i)
for (int i = 1; i <= n; i++) {
sum[i] = sum[i - 1] + ceilDivided(p, i);
}
for (int i = 1; i <= n; i++) {
cin >> h[i];
}
for (int i = 0; i <= n; i++) {
st[i][0] = {h[i], i};
}
for (int j = 1; j <= 17; j++) {
for (int i = 1; i + (1 << j) - 1 <= n; i++) {
st[i][j] = min(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]);
}
}
solve(1, n);
cout << ans << endl;
return 0;
}

一般的,如果对于一道题,统计方案时有最大值或最小值作为阻碍/瓶颈,可以考虑分治。

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

安吉D2-T2
https://blog.jerrylab.top/posts/problem/anji2026/D2/T2/
作者
Jerry
发布于
2026-08-02
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
Jerry
Hello, I'm Jerry.
公告
欢迎来到我的博客!这是一则示例公告。
分类
标签
最新动态
站点统计
文章
80
分类
3
标签
35
总字数
89,198
运行时长
0
最后活动
0 天前
站点信息
构建平台
Cloudflare Pages
博客版本
Firefly v6.16.5
文章许可
CC BY-NC-SA 4.0