NOIP 2013 D2T1 积木大赛

本文介绍了NOIP2013-D2T1积木大赛的问题背景及解决思路,通过使用单调队列来优化算法,实现搭建积木大厦所需的最少操作次数。

【NOIP2013-D2T1】积木大赛

Time Limit:10000MS  Memory Limit:128000K
Total Submit:49 Accepted:43
Case Time Limit:1000MS

Description

春春幼儿园举办了一年一度的“积木大赛”,今年比赛的内容是搭建一座宽度为n的大厦。
大厦可以看成由块宽度为n的积木组成,第i块积木的最终高度需要是hi。
在搭建开始之前,没有任何积木(可以看成n块高度为0的积木)。接下来每次操作,小朋友们可以选择一段连续区间[L,R],然后将第L块到第R块之间(含第L块和第R块)所有积木的高度分别增加1。
小M是个聪明的小朋友,她很快想出了建造大厦的最佳策略,使得建造所需的操作次数最少。但她不是一个勤于动手的孩子,所以想请你帮忙实现这个策略,并求出最少的操作次数。

Input

输入包含两行,第一行包含一个整数n,表示大厦的宽度。
第二行包含n个整数,第 个整数为hi。

Output

仅一行,即建造所需的最少操作数。

Sample Input

5 
2 3 4 1 2 

Sample Output

5

Hint

【样例解释】
其中一种可行的最佳方案,依此选择
[1,5] [1,3] [2,3] [3,3] [5,5]


【数据范围】
对于 30%的数据,有1<=n<=10;
对于 70%的数据,有1<=n<=1000;
对于 100%的数据,有1<=n<=100000,0<=hi<=10000。


明明很简单的一道题……却想了好久

我算是发现了,去NOIP比赛的时候一道题的代码不一定是你写不出来,而是你根本没想到这种解法,所以只有多看才能涨姿势啊

这道题我开始想用扫描来做,结果不行……,后来才知道用单调队列

用单调队列的理由很简单,如果有一个连续不递减区间那么这段区间的最佳方案就是最高的一个的高度,因此讨论到每一个i的时候就将这个i加到队列中去

每当s[i]<q.back()的时候ans+=q.back()-s[i],这里的意思就是将前面所有的高度都转换为i的高度,然后这样就又一次满足了单调队列,就继续讨论就可以了

#include<cstdio>
#include<iostream>
#include<queue>
using namespace std;
const int maxn=1e5+5;
inline void _read(int &x){
    char t=getchar();bool sign=true;
    while(t<'0'||t>'9')
    {if(t=='-')sign=false;t=getchar();}
    for(x=0;t>='0'&&t<='9';t=getchar())x=x*10+t-'0';
    if(!sign)x=-x;
}
int n,s[maxn],ans;
queue<int>q;
int main(){
	int i,j;
	_read(n);
	for(i=1;i<=n;i++)_read(s[i]);
	for(i=1;i<=n;i++){
		if(q.size()&&q.back()>s[i])ans+=q.back()-s[i];
		q.push(s[i]);
	}
	cout<<ans+q.back();
}


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值