题目描述
春春幼儿园举办了一年一度的“积木大赛”。今年比赛的内容是搭建一座宽度为n的大厦,大厦可以看成由n块宽度为1的积木组成,第i块积木的最终高度需要是hi。
在搭建开始之前,没有任何积木(可以看成n块高度为0的积木)。接下来每次操作,小朋友们可以选择一段连续区间[l,r],然后将第第LL块到第 R 块之间(含第L 块和第 R块)所有积木的高度分别增加1。
小M是个聪明的小朋友,她很快想出了建造大厦的最佳策略,使得建造所需的操作次数最少。但她不是一个勤于动手的孩子,所以想请你帮忙实现这个策略,并求出最少的操作次数。
输入格式
包含两行,第一行包含一个整数n,表示大厦的宽度。
第二行包含n个整数,第i个整数为hi。
输出格式
建造所需的最少操作数。
输入输出样例
输入 #15 2 3 4 1 2输出 #15说明/提示
【样例解释】
其中一种可行的最佳方案,依次选择
[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是怎么只骗了30分的。
用极不优雅的方式A了。
1 #include<bits/stdc++.h> 2 #define re register int 3 #define maxn 100000+5 4 5 using namespace std; 6 int n; 7 int h[maxn]; 8 int cnt; 9 void solve(int l,int r) 10 { 11 if(l>r) return; 12 if(l==r){ 13 cnt+=h[l]; 14 return; 15 } 16 int minh=19260817; 17 for(re i=l;i<=r;i++) 18 minh=min(minh,h[i]); 19 cnt+=minh; 20 int las=l; 21 for(re i=l;i<=r;i++) 22 { 23 h[i]-=minh; 24 if(h[i]==0) solve(las,i-1),las=i+1; 25 } 26 if(las<=r) solve(las,r); 27 } 28 int main() 29 { 30 ios::sync_with_stdio(false); 31 cin>>n; 32 for(re i=1;i<=n;i++) 33 cin>>h[i]; 34 solve(1,n); 35 cout<<cnt; 36 return 0; 37 }
用优雅的方式写了一遍,然而又没有输出了(。)
1 #include<bits/stdc++.h> 2 #define re register int 3 #define maxn 100000+5 4 5 using namespace std; 6 int n; 7 int h[maxn]; 8 int cnt; 9 void solve(int l,int r) 10 { 11 if(l>r) return; 12 if(l==r){ 13 cnt+=h[l]; 14 return; 15 } 16 int minh=19260817; 17 for(re i=l;i<=r;i++) 18 minh=min(minh,h[i]); 19 cnt+=minh; 20 int las=l; 21 for(re i=l;i<=r;i++) 22 { 23 h[i]-=minh; 24 if(h[i]==0) 25 if(las<=i-1) 26 solve(las,i-1),las=i+1; 27 } 28 if(las<=r) solve(las,r); 29 } 30 int main() 31 { 32 ios::sync_with_stdio(false); 33 cin>>n; 34 for(re i=1;i<=n;i++) 35 cin>>h[i]; 36 solve(1,n); 37 cout<<cnt; 38 return 0; 39 }