一开始想用栈来做,栈要保存两个数:一为高度,二为横坐标,主要是比较当前值temp与下一个值next的大小:如果temp大或等于,就将temp压入栈中,否则,就比较next与栈中元素的大小:如果栈中元素小就出栈,并更新ans+=(栈值-temp)*(next横坐标 - 栈的横坐标-1),将temp更新为出栈的值,再继续检查下一个栈中值是否大于next;如果如果栈中元素>=,ans+=(栈值-next)*(next横坐标 - 栈的横坐标-1);最后令temp=next;
但这样做感觉时间不够,之后就用整体的思维来做:就是将整个城市都淹没,水之后慢慢流失,先计算最高层和次高层之间的积水,p0为两者之间横坐标较大的横坐标,p1为两者之间横坐标较小的横坐标;之后p1与p2之外的积水,计算积水时我有用到前n项和sum[n]=sum[n-1]+a[n];看来基础会在不经意间发挥作用;(在n==1的时候要进行特判)
(后记:可以用单调队列来解)
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=100010;
struct node{
int p,h;
};
node pos[maxn];
bool cmp(node a,node b){
if(a.h==b.h)return a.p>b.p;
return a.h>b.h;
}
int sum[maxn];
int main()
{
int T;
scanf("%d",&T);
while(T--){
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&pos[i].h);
pos[i].p=i;
if(i)sum[i]=sum[i-1]+pos[i].h;
else sum[i]=pos[i].h;
}
if(n==1){
printf("0\n");continue;
}
sort(pos,pos+n,cmp);
int p0=max(pos[0].p,pos[1].p);
int p1=min(pos[0].p,pos[1].p);
int ans=(p0-p1-1)*pos[1].h-(sum[p0-1]-sum[p1]);
for(int i=2;i<n;i++){
if(pos[i].p>p0){
ans+=(pos[i].p-p0-1)*pos[i].h-(sum[pos[i].p-1]-sum[p0]);
p0=pos[i].p;
}
else if(pos[i].p<p1){
ans+=(p1-pos[i].p-1)*pos[i].h-(sum[p1-1]-sum[pos[i].p]);
p1=pos[i].p;
}
}
printf("%d\n",ans);
}
return 0;
}