GDUT 广东工业大学网络赛 E 积木积水

Problem E: 积木积水

Description

现有一堆边长为1的已经放置好的积木,小明(对的,你没看错,的确是陪伴我们成长的那个小明)想知道当下雨天来时会有多少积水。小明又是如此地喜欢二次元,于是他把这个三维的现实问题简化成二维的问题。设雨量无穷、积木不透水、积木间无缝连接,问在这个二次元的世界里,已放置好的积木会有多少单位的积水量?

GDUT 广东工业大学网络赛 E 积木积水_第1张图片

Input

第一行包含一个整数T(T≤100),表示接下来的测试样例个数。 每个测试样例有两行组成: 第一行包含一个整数N(N≤1e6),表示积木的列数; 第二行包含N个整数Ai(Ai≤1e6),表示第i列积木的个数。

Output

每个样例输出一行,包含一个整数,为题目所求。

Sample Input

1116 2 2 4 2 0 3 4 4 5 1

Sample Output

19

比赛时做这道题一脸懵逼,起初我想了种方法,就是先找到最高的那个,然后向左向

找次高的,并计算中间的存水数,可是关键怎么找次高的是个问题,如果一遍一遍遍

历的话,肯定TLE,比赛完学长说可以用rmq来解决这个问题,后来看了别人用栈来写

,果然好用,平时很少用栈,比赛的时候根本想不到,看来以后要常用STL了。


#include<stdio.h>
#include<string.h>
#include<stack>
using namespace std;
long long a[1000010],b[1000010];
int main()
{
     int N,n;
     scanf ( "%d" ,&N);
     while (N--)
     {
         stack< int >q;
         scanf ( "%d" ,&n);
         long long i,s=0,t;
         memset (b,0, sizeof (b));
         for (i=1; i<=n; i++)
         scanf ( "%d" ,&a[i]),b[i]=a[i];
             for (i=2; i<=n; i++)
             b[i]+=b[i-1];
         for (i=1; i<=n; i++)
         {
             if (q.empty())
             {
                 q.push(i);
                 continue ;
             }
             while (!q.empty())
             {
                  t=q.top();
                 if (a[t]<a[i])
                     q.pop();
                     else
                     break ;
             }
             if (q.empty())
                 s+=(i-t-1)*a[t]-b[i-1]+b[t];
             q.push(i);
         }
         while (!q.empty())
         {
             i=q.top();
             q.pop();
             if (!q.empty())
             {
                t=q.top();
             s+=(i-t-1)*a[i]-b[i-1]+b[t];
             }
         }
         printf ( "%lld\n" ,s);
     }
}

你可能感兴趣的:(栈)