zoukankan      html  css  js  c++  java
  • bzoj1233[USACO2009 Open]Tower of Hay干草金字塔

    题目链接: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;
    }
    这题,真的,让我真正开始理解了单调队列!

  • 相关阅读:
    ZOJ 2604 Little Brackets DP
    js实现回放拖拽轨迹-------Day48
    Android蓝牙开发
    linux中的两个很重要的信号:SIGALRM信号和SIGCHID信号
    MySQL mysqldump数据导出详解
    JFinal redis cluster集群插件
    nginx平滑升级
    温故而知新-String类
    Linux环境变量具体解释
    android消息机制
  • 原文地址:https://www.cnblogs.com/Euryale-Rose/p/6527849.html
Copyright © 2011-2022 走看看