这道题还真是像黄学长说的一样的神题啊。。。
题意看起来很普通 可是实际上却不是。
好像DP 好像贪心 好像想法题,后来发现都需要。
怎么觉得我最近做的题都要个证明啊。。。实在不懂的就yy一下吧 差不多就是酱
接着不难发现倒推会发现单调
这样之后就可以得到O(N^2)的DP
f[i]:用i
~
n来构成的堆,最靠下的一层最短是多少
g[i]:状态f[i]的最大高度
f[i]=min{sum[j−1]−sum[i−1]} (i<j≤n,f[j]≤sum[j−1]−sum[i−1])
然后我们可以发现
当有两个决策点j<k且sum[k−1]−f[k]≤sum[j−1]−f[j]时,k可以被剔除(不懂的你该好好想了)
然后我们就用到单调队列啦啦啦~
#include<cstdio>
using namespace std;
const int N=100010;
int s[N],q[N],h,t,g[N],f[N];
int main()
{
int n,i,x;
scanf("%d",&n);
for(i=1;i<=n;i++)scanf("%d",&x),s[i]=s[i-1]+x;
h=t=1; q[t]=n+1;
for(i=n;i;i--)
{
while(h<t && f[q[h+1]]<=s[q[h+1]-1]-s[i-1])h++;
x=q[h];
g[i]=g[x]+1,f[i]=s[x-1]-s[i-1];
while(h<t && f[i]-s[i-1]<f[q[t]]-s[q[t]-1])t--;
q[++t]=i;
}
printf("%d\n",g[1]);
return 0;
}