题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1233权限题
题目大意:
题解:
单调队列优化
首先要证一个东西,就是底层最瘦的金字塔一定能搭成最高的。
[然而我并不怎么会,所以引用一下马融大大的证明:]
设f[i]为做到i的时候最后一层的最小宽度为多少。g[i]记录搭到i时的最高层数
(sum[i]为前缀和
我是从后开始做的,为了方便打,就在输入的时候直接倒过来了。
于是相当于我是从顶层开始搭起,那么方程就是:
f[i]=sum[i]-sum[j];j满足f[j]<=sum[i]-sum[j] (j<i)
即 j要满足sum[i]>=sum[j]+f[j]。故对于i来说,若有k<j,且sum[j]+f[j]<sum[k]+f[k]的话,j比k要优,k是可以被舍弃的。所以要维护一个sum[i]+f[i]单调递增的单调队列。
#include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<iostream> using namespace std; #define maxn 101000 int w[maxn],f[maxn]; int g[maxn],q[maxn],sum[maxn]; int main() { //freopen("pyramid.in","r",stdin); //freopen("pyramid.out","w",stdout); int n,i,l,r; scanf("%d",&n);sum[0]=0; for (i=n;i>=1;i--) scanf("%d",&w[i]); for (i=1;i<=n;i++) sum[i]=sum[i-1]+w[i]; g[0]=0;l=1;r=1;q[1]=0; for (i=1;i<=n;i++) { while (l<r && sum[i]>=sum[q[l+1]]+f[q[l+1]]) l++; int j=q[l]; f[i]=sum[i]-sum[j]; g[i]=g[j]+1; while (l<r && sum[q[r]]+f[q[r]]>=sum[i]+f[i]) r--; q[++r]=i; } printf("%d ",g[n]); return 0; }这题,真的,让我真正开始理解了单调队列!