Problem E: 积木积水
Description
现有一堆边长为1的已经放置好的积木,小明(对的,你没看错,的确是陪伴我们成长的那个小明)想知道当下雨天来时会有多少积水。小明又是如此地喜欢二次元,于是他把这个三维的现实问题简化成二维的问题。设雨量无穷、积木不透水、积木间无缝连接,问在这个二次元的世界里,已放置好的积木会有多少单位的积水量?
Input
第一行包含一个整数T(T≤100),表示接下来的测试样例个数。 每个测试样例有两行组成: 第一行包含一个整数N(N≤1e6),表示积木的列数; 第二行包含N个整数Ai(Ai≤1e6),表示第i列积木的个数。
Output
每个样例输出一行,包含一个整数,为题目所求。
Sample Input
1 11 6 2 2 4 2 0 3 4 4 5 1
Sample Output
19
略微思考一下能发现一个规律,每一个木块上方,能够有多少的水,取决于它左端最高的木块和右端最高的木块里小的那个。
预处理两个数组after 和 pre ,after[i] 是 第i个 方块向后找能找到的最高的方块,pre同理。复杂度大概是 O(3 * n) 吧。。。
1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 long long h[1000010]; 5 long long after[1000010]; 6 long long pre[1000010]; 7 int main(){ 8 int T; 9 while(~scanf("%d",&T)) while(T--){ 10 int n; 11 scanf("%d",&n); 12 for(int i = 0 ; i < n ; i++){ 13 scanf("%lld",h + i); 14 } 15 after[n - 1] = h[n - 1]; 16 pre[0] = h[0]; 17 for(int i = n - 2 ; i >= 0 ; i--){ 18 after[i] = max(h[i],after[i + 1]); 19 } 20 for(int i = 1 ; i < n ; i++){ 21 pre[i] = max(h[i],pre[i - 1]); 22 } 23 long long ans = 0; 24 25 for(int i = 0 ; i < n ; i++){ 26 ans += (min(pre[i] , after[i]) - h[i]); 27 } 28 printf("%lld\n", ans); 29 } 30 return 0; 31 }
时间: 2024-12-15 07:11:00