题解:P11261 [COTS 2018] 直方图 Histogram
更好的阅读体验?
码字不易,帮到你的话点个关注谢谢
LGP11261 [COTS 2018] 直方图 学习笔记
Luogu Link
前言
参考了这篇题解。算是对其更详细的一个解释。
题意简述
给定一宽为
给定正整数
- 有一条边在
x 轴上。 - 完全位于直方图内部。
- 面积至少为
p 。
做法解析
首先想一想当一个矩形面积至少为
我们发现,当矩形的
令当前结点
考虑枚举较小的那一侧子树的
显然最小的满足
所以上式等价于算
也即等价于
注意到我们减去的那玩意就是个
时间复杂度
代码实现
代码很简单!
#include <bits/stdc++.h>
using namespace std;
namespace obasic{
typedef long long lolo;
template <typename _T>
void readi(_T &x){
_T k=1;x=0;char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')k=-1;
for(;isdigit(ch);ch=getchar())x=(x<<3)+(x<<1)+ch-'0';
x*=k;return;
}
template <typename _T>
void writi(_T x){
if(x<0)putchar('-'),x=-x;
if(x>9)writi(x/10);
putchar(x%10+'0');
}
template <typename _T>
void maxxer(_T &x,_T y){x=max(x,y);}
template <typename _T>
_T pcedi(_T x,_T y){return (x-1)/y+1;}
};
using namespace obasic;
const int MaxN=1e5+5;
int N,H[MaxN],stk[MaxN],ktp;
int ls[MaxN],rs[MaxN];lolo P,pre[MaxN],ans;
lolo calc(lolo l,lolo r,lolo h){
maxxer(l,pcedi(P,h));if(l>r)return 0;
return 1ll*(h+1)*(r-l+1)-(pre[r]-pre[l-1]);
}
lolo solve(int u,int cl,int cr){
lolo res=0;int lsiz=u-cl,rsiz=cr-u;
if(lsiz>rsiz)swap(lsiz,rsiz);
lsiz++;for(int i=1;i<=lsiz;i++)res+=calc(i,i+rsiz,H[u]);
if(ls[u])res+=solve(ls[u],cl,u-1);
if(rs[u])res+=solve(rs[u],u+1,cr);
return res;
}
signed main(){
readi(N),readi(P);
for(int i=1;i<=N;i++)pre[i]=pre[i-1]+pcedi(P,(lolo)i);
for(int i=1;i<=N;i++)readi(H[i]);
for(int i=1;i<=N;i++){
int k=ktp;
while(k&&H[stk[k]]>H[i])k--;
if(k)rs[stk[k]]=i;
if(k<ktp)ls[i]=stk[k+1];
stk[++k]=i,ktp=k;
}
ans=solve(stk[1],1,N);writi(ans);
return 0;
}
反思总结
我们考虑有顺序地枚举限制矩形高度的
更深刻的东西暂时想不出来/ll