P2897题解
本题题意如下图。
图中,两边无限高,而
那么,实际上就是一个单调递减栈。
如果进栈元素比栈顶高,那么栈内比它矮的都先注满,再出来,累加出栈元素的宽度,实现过程如下图。
那么代码就是下面这样。
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e6+50;
struct pingtai
{
long long kuandu;//平台宽度
long long gaodu;//平台高度
}a[N];
long long ans[N],sta[N][2],tt,temp,minn=100000099,sta1[N];
int main()
{
long long n,zz=0;
cin>>n;
a[0].gaodu=9999999999;//题目说了,两边无限高
a[n+1].gaodu=9999999999;//奶牛:我上不来了
for(long long i=1;i<=n;i++)
{
cin>>a[i].kuandu>>a[i].gaodu;
if(a[i].gaodu<minn)
{
minn=a[i].gaodu;//最矮平台
temp=i;//最矮平台下标
}
}
sta1[++tt]=temp;
long long now=0;//现在所用时间
long long l=temp-1,r=temp+1;//l:最矮平台左边那个平台的下标;r:最矮平台右边那个平台的下标
for(long long i=1;i<=n;i++)
{
long long xx,yy;//分别记录高度和宽度
long long kuan=0;//用来累计宽度
if(a[l].gaodu<a[r].gaodu)//如果l平台比r平台矮,就该往l平台注水
{
xx=a[l].gaodu;
yy=a[l].kuandu;//统计
while(tt>0 && a[l].gaodu>a[sta1[tt]].gaodu)//单调递减栈
{
a[sta1[tt]].kuandu+=kuan;
ans[sta1[tt]]=now+a[sta1[tt]].kuandu;//填满这个地方所需时间就是宽度*1,直接加上宽度就可以了
kuan=a[sta1[tt]].kuandu;//加上栈顶宽度
now+=(min(a[sta1[tt-1]].gaodu,a[l].gaodu)-a[sta1[tt]].gaodu)*a[sta1[tt]].kuandu;
tt--;
}
a[l].kuandu+=kuan;//进栈平台宽度要加上出栈平台的宽度
sta1[++tt]=l;
l--;//l一直向左移,所以--,r相反
}
else
{
xx=a[r].gaodu;
yy=a[r].kuandu;//统计
while(tt>0 && a[r].gaodu>a[sta1[tt]].gaodu)//单调递减栈
{
a[sta1[tt]].kuandu+=kuan;
ans[sta1[tt]]=now+a[sta1[tt]].kuandu;//填满这个地方所需时间就是宽度*1,直接加上宽度就可以了
kuan=a[sta1[tt]].kuandu;//加上栈顶宽度
now+=(min(a[sta1[tt-1]].gaodu,a[r].gaodu)-a[sta1[tt]].gaodu)*a[sta1[tt]].kuandu;
tt--;
}
a[r].kuandu+=kuan;//进栈平台宽度要加上出栈平台的宽度
sta1[++tt]=r;
r++;
}
}
for(long long i=1;i<=n;i++)
{
cout<<ans[i]<<endl;
}
return 0;
}