【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();
}

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

被折叠的 条评论
为什么被折叠?



