原题链接:
题意:一排方格,有的方格上放了空调,空调温度向两边扩散上升。
求每个位置能够得到的最低温度为多少。
一个位置i的最低温度为min(a[x]+|i-x|),x为空调所在位置。
思路:每个位置左半区间的最低温度和右半区间的最低温度取min。
维护左区间、右区间两个单调栈。
栈中存放的是空调的所在位置及其温度。
左区间:如果当前位置有空调:
若:当前位置i的温度<=栈顶元素+i-栈顶元素所在位置
则栈顶元素永远用不到了,出栈。
因为后面的位置计算温度时,只是加上了两点间的位置差。
这样就维护出了一个单调递增的单调栈。
栈底元素就是温度最低的空调温度和位置。
Code:
#include<iostream>
#include<cstring>
using namespace std;
typedef long long LL;
const int N=300010;
int n,m,a[N],b[N];
LL l[N],r[N];
pair<int,int> stk[N];
int main(){
int T;
cin>>T;
while(T--)
{
cin>>n>>m;
memset(b,0,sizeof b);
memset(a,0,sizeof a);
for(int i=1;i<=m;i++) scanf("%d",&b[i]);
for(int i=1;i<=m;i++) scanf("%d",&a[b[i]]);
int top=0; //左半区间单调栈,求左半区间的最小温度
for(int i=1;i<=n;i++)
{
if(a[i]){
while(top>=1&&a[i]<=stk[top].first+i-stk[top].second) top--;
stk[++top]={a[i],i};
}
if(top) l[i]=stk[1].first+i-stk[1].second;
else l[i]=1e10;
}
top=0; //右半区间单调栈,求右半区间的最小温度
for(int i=n;i>=1;i--)
{
if(a[i]){
while(top>=1&&a[i]<=stk[top].first+stk[top].second-i) top--;
stk[++top]={a[i],i};
}
if(top) r[i]=stk[1].first+stk[1].second-i;
else r[i]=1e10;
}
for(int i=1;i<=n;i++) cout<<min(l[i],r[i])<<" ";
cout<<endl;
}
return 0;
}