题解:P11261 [COTS 2018] 直方图 Histogram
这么经典的题必须来篇题解。
看到这种矩形统计方案数的题目我们不难想到建立一颗小根堆笛卡尔树。
现在对于这个节点
所以我们考虑对于这个笛卡尔树做分治,在
但是这样时间复杂度显然是
那么我们只有
不难注意到这其实是一段连续的区间是可以考虑
但是这个
拆一下式子(设
你不难注意到这个最后的求和式子是可以前缀和算的,然后只枚举
:::success[Ac Code]
#include<bits/stdc++.h>
using namespace std;
#ifdef __linux__
#define gc getchar_unlocked
#define pc putchar_unlocked
#else
#define gc _getchar_nolock
#define pc _putchar_nolock
#endif
#define int long long
#define ull unsigned long long
// #define R register
#define rint register int
#define _ read<int>()
inline bool blank(const char &x)
{
return !(x^13)||!(x^32)||!(x^10)||!(x^9);
}
template<class T>inline T read()
{
T r=0,f=1;char c=gc();
while(!isdigit(c))
{
if(c=='-') f=-1;
c=gc();
}
while(isdigit(c)) r=(r<<1)+(r<<3)+(c^48),c=gc();
return f*r;
}
inline void out(rint x)
{
if(x<0) pc('-'),x=-x;
if(x<10) pc(x+'0');
else out(x/10),pc(x%10+'0');
}
inline void read(char &x)
{
for(x=gc();!blank(x)&&(x^-1);x=gc());
}
const int N=1e5+10;
struct Node
{
int ls,rs,x;
}tr[N];
int n,p,sta[N],top,rt,s[N],ans;
inline void dfs(rint u,rint l,rint r)
{
if(!u) return;
// cerr<<u<<' '<<l<<' '<<r<<endl;
dfs(tr[u].ls,l,u-1);
dfs(tr[u].rs,u+1,r);
if(u-l<=r-u)
{
for(rint L=l;L<=u;++L)
{
rint A=max((p+tr[u].x-1)/tr[u].x,u-L+1),B=r-L+1;
if(A<=B) ans+=(tr[u].x+1)*(B-A+1)-(s[B]-s[A-1]);
}
}
else
{
for(rint R=u;R<=r;++R)
{
rint A=max((p+tr[u].x-1)/tr[u].x,R-u+1),B=R-l+1;
if(A<=B) ans+=(tr[u].x+1)*(B-A+1)-(s[B]-s[A-1]);
}
}
}
signed main()
{
n=_,p=_;
for(rint i=1;i<=n;++i) tr[i]={0,0,_};
for(rint i=1;i<=n;++i)
{
while(top&&tr[sta[top]].x>tr[i].x) --top;
if(top) tr[i].ls=tr[sta[top]].rs,tr[sta[top]].rs=i;
else tr[i].ls=sta[top+1],rt=i;
sta[++top]=i;
}
for(rint i=1;i<=n;++i) s[i]=s[i-1]+(p+i-1)/i;
dfs(rt,1,n);
out(ans);
return 0;
}
//我也要写吗
:::