描述:
现有一堆边长为1的已经放置好的积木,小明(对的,你没看错,的确是陪伴我们成长的那个小明)想知道当下雨天来时会有多少积水。小明又是如此地喜欢二次元,于是他把这个三维的现实问题简化成二维的问题。设雨量无穷、积木不透水、积木间无缝连接,问在这个二次元的世界里,已放置好的积木会有多少单位的积水量?
输入:
第一行包含一个整数T(T≤100),表示接下来的测试样例个数。 每个测试样例有两行组成: 第一行包含一个整数N(N≤1e6),表示积木的列数; 第二行包含N个整数Ai(Ai≤1e6),表示第i列积木的个数。
输出
每个样例输出一行,包含一个整数,为题目所求。
sample input
1
11
6 2 2 4 2 0 3 4 4 5 1
sample output
19
求有多少积水,递减栈做就好
#include <cstdio>
#include <iostream>
#include <cstring>
#include <stack>
//维护一个递减栈
using namespace std;
long long d[1000005];
long long num[1000005];
using namespace std;
int main (void)
{
int t,n;
cin>>t;
while(t--)
{
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%lld",&d[i]);
}
num[0]=d[0];
for(int i=1;i<n;i++)
{
num[i]=num[i-1]+d[i];
}
stack<int>s;
long long ans=0;
int t;
for(int i=0;i<n;i++)
{
if(s.empty())
{
s.push(i);
continue;
}
while(!s.empty())
{
t=s.top();
if(d[t]>d[i])
break;
s.pop();
}
if(s.empty())
ans+=(i-t-1)*d[t]-(num[i-1]-num[t]);
s.push(i);
}
if(!s.empty())
{
int i=s.top();
s.pop();
while(!s.empty()){
int t=s.top();
s.pop();
ans+=(i-t-1)*d[i]-(num[i-1]-num[t]);
i=t;
}
}
printf("%lld\n",ans);
}
return 0;
}//有趣的栈hhh