LGP11261 [COTS 2018] 直方图 学习笔记
LGP11261 [COTS 2018] 直方图 学习笔记
前言
参考了这篇题解。算是对其更详细的一个解释。
题意简述
给定一宽为 \(n\) 的直方图,第 \(i\) 格的高度为 \(a_i\)。
给定正整数 \(S\),求出满足以下条件的网格矩形的数量:
- 有一条边在 \(x\) 轴上。
- 完全位于直方图内部。
- 面积至少为 \(S\)。
\(n\le 10^5,a_i\le 10^9,S\le 10^{14}\)。
做法解析
要求的矩形都形如 \((l,0),(r,0),(r,h_u),(l,h_u)\)。
确定矩形的高 \(b\) 就随之确定了 \(a\ge \lceil \frac{S}{b} \rceil\)。
我们发现,当矩形的 \(l,r\) 确定之后,限制 \(h_u\) 范围的正是 \([l,r]\) 中 \(a_i\) 的最小值。此时套路来了:我们以 \(u\) 为键,\(h_u\) 为值建一棵小根笛卡尔树,并考虑横跨每个最小值的贡献。具体来说我们对这棵笛卡尔树做一遍 \(dfs\),每搜到一个结点 \((u,h_u)\),设其在笛卡尔树上管辖的区间为 \([lb_u,rb_u]\),我们就统计所有 \(lb_u\le l\le u,u\le r\le rb_u\) 的合法矩形的数量。这么做可以不重不漏地计数。

记 \(L=u-lb,R=u-rb\),现在答案可以写作:
其中的 \(\lceil\frac{S}{i+j+1}\rceil\) 代表着 \(i,j\) 确定后合法矩形高度的最小值,\(a_u-\lceil\frac{S}{i+j+1}\rceil+1\) 则自然是 \(i,j\) 确定后合法高度的种类。
由启发式合并思想,为了保证复杂度,考虑枚举较小的那一侧子树的 \(i\),此处不妨设 \(L<R\)。我们又让第二维改为枚举矩形的长度,上式现在可以写作:
又:\(a_u-\lceil\frac{S}{k}\rceil+1\ge 0\) 即 \(\lceil\frac{S}{k}\rceil\le a_u+1\)。
显然最小的满足 \(\lceil\frac{S}{k}\rceil\le a_u+1\) 的 \(k\) 就是 \(\lceil\frac{S}{a_u+1}\rceil\)。
\(\lceil\frac{S}{x}\rceil\le y\to xy\ge S\to x\ge\lceil\frac{S}{y}\rceil\)
就是这样,稍微写一句以防我忘了。
记 \(k_0=\max(i+1,\lceil\frac{S}{a_u+1}\rceil)\),则上式等价于
也即等价于
最后减去的那一坨东西,通过预处理 \(\lceil \frac{S}{i} \rceil\) 的前缀和即可快速求值。这道题就做完了!
时间复杂度 \(O(n\log n)\)。
代码实现
代码很简单!
#include <bits/stdc++.h>
using namespace std;
using namespace obasic;
const int MaxN=1e5+5;
int N;lolo A[MaxN],S,pre[MaxN],ans;
int ls[MaxN],rs[MaxN],stk[MaxN],ktp;
lolo calc(int u,int ci,int rs){
lolo cl=max(lolo(ci+1),pcedi(S,A[u]+1));
lolo cr=ci+rs+1;if(cl>cr)return 0;
return (cr-cl+1)*(A[u]+1)-(pre[cr]-pre[cl-1]);
}
void solve(int u,int cl,int cr){
int lsiz=u-cl,rsiz=cr-u;
if(lsiz>rsiz)swap(lsiz,rsiz);
for(int i=0;i<=lsiz;i++)ans+=calc(u,i,rsiz);
if(ls[u])solve(ls[u],cl,u-1);
if(rs[u])solve(rs[u],u+1,cr);
}
int main(){
readis(N,S);
for(int i=1;i<=N;i++)pre[i]=pre[i-1]+pcedi(S,lolo(i));
for(int i=1;i<=N;i++)readi(A[i]);
for(int i=1,k;i<=N;i++){
k=ktp;
while(k&&A[stk[k]]>A[i])k--;
if(k)rs[stk[k]]=i;
if(k<ktp)ls[i]=stk[k+1];
stk[++k]=i,ktp=k;
}
solve(stk[1],1,N),writi(ans);
return 0;
}
反思总结
我们考虑有顺序地枚举限制矩形高度的 \(h_i\),于是把问题搬到了笛卡尔树上!
这是什么?这是“极值分治”的思想。其过程就是建笛卡尔树的过程。
浙公网安备 33010602011771号