题解:P10654 [ROI 2017] 水星上的服务器 (Day 2)
MaiJingYao666 · · 题解
P10654 [ROI 2017] 水星上的服务器 (Day 2) 题解
不难想的一道思维题。
解题思路
刚开始看有点复杂,但发现显然这是一条链,所以要考虑的就是信息往左传递的时间和往右传递的时间。我们设
考虑转移,首先先看一下无解的情况。向左传递时如果节点
那么怎么正常转移呢?还是以向左转移为例,首先,
最后就是我们把向左向右的推出来了,怎么确定呢?显然当两个区间没有交集时,没办法周全,那就是
AC 代码
#include<iostream>
using namespace std;
const int N=2e5+5;
const int Maxn=1e9;
int n;
int t[N];
int l[N],r[N];
int ll[N],lr[N],rl[N],rr[N];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&t[i]);
}
for(int i=1;i<n;i++){
scanf("%d%d",&l[i],&r[i]);
}
ll[1]=0,lr[1]=Maxn;
for(int i=2;i<=n;i++){
if(l[i-1]>lr[i-1] || r[i-1]<ll[i-1]){
for(int j=i;j<=n;j++){
ll[j]=-1;
lr[j]=-1;
}
break;
}
lr[i]=min(lr[i-1],r[i-1]);
if(ll[i-1]<=l[i-1]) ll[i]=max(0,l[i-1]-t[i]);
else ll[i]=ll[i-1];
}
rl[n]=0,rr[n]=Maxn;
for(int i=n-1;i>=1;i--){
if(l[i]>rr[i+1] || r[i]<rl[i+1]){
for(int j=i;j>=1;j--){
rl[j]=-1;
rr[j]=-1;
}
break;
}
rr[i]=min(rr[i+1],r[i]);
if(rl[i+1]<=l[i]) rl[i]=max(0,l[i]-t[i]);
else rl[i]=rl[i+1];
}
for(int i=1;i<=n;i++){
// cout<<ll[i]<<" "<<lr[i]<<" "<<rl[i]<<" "<<rr[i]<<" ";
if(ll[i]==-1 || rl[i]==-1 || ll[i]>rr[i] || rl[i]>lr[i]){
printf("-1\n");
}
else printf("%d\n",max(ll[i],rl[i]));
}
}
/*
a~b
c~d
*/