LA 4725 Airport
题目大意:
一个机场,只有一根跑道,有W和E两方的飞机,每一时刻可以选择一架飞机起飞,先选择一架飞机起飞后,该时刻又会增加一些飞机.飞机的编号由0开始,所以任意时刻W和E方的飞机最大编号为该方飞机数量-1.求如何安排飞机起飞,使得任意时刻下飞机最大编号最小.
(注:没有在题面上面看到若没飞机怎么办,感觉是输出0)
题目分析:
(感觉最近越来越蠢了,用了3~4h写这个题,WA了无数次)
最大最小双最值问题,思考二分答案方面,难点主要在check上.
一开始想的是用W和E表示两方的飞机数,now表示当前还可以飞多少个飞机.
如遇到W/E大于ans,判断是否能用now使得W/E小于等于ans,然而……WA了.
想了想,发现了一个问题没有考虑到,若某一时刻进入的飞机是0怎么办,想的是那么就只有另外一方减去一,然而……WA了.
后知后觉,发现了一个问题,比如某一时刻W方进入的飞机为0个,其实也可以飞走W方的飞机,只要W方有就行了.到了这里,若采取和一开始类似的方法,是不行的.原因在于,你是只在数目超过ans时,才飞多个飞机,而实际上,飞机是在每一时刻飞架飞机的.所以需要引入两个变量nw和ne,记录每一方最多能飞走多少飞机,now表示两方最多能飞走多少飞机.这个样子才能够确保不会飞走多的飞机.
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=5000+10;
int w[maxn],e[maxn],n;
bool check(int ans)
{
int W=0,E=0,nw=0,ne=0,now=0;//W/E 表示两方的飞机数 nw/ne表示两方最多可以减去多少 now表示总共最多可以减去多少
for(int i=0;i<n;i++) {
W+=w[i];E+=e[i];
if(W>ans) {//若飞机数大于ans,将飞机数减至ans
if(W-ans>nw||W-ans>now) return false;//若减不了那么多,ans不成立
nw-=W-ans;now-=W-ans;W=ans;
}
if(E>ans) {
if(E-ans>ne||E-ans>now) return false;
ne-=E-ans;now-=E-ans;E=ans;
}
if(nw<W) ++nw;//只有当W还可以飞走飞机的时候nw才增加,否则当前时刻从W方飞走飞机
if(ne<E) ++ne;
if(now<W+E) ++now;
}
return true;
}
int main()
{
int T;
scanf("%d",&T);
while(T--) {
scanf("%d",&n);
int L=1,R=0;//若没有飞机,似乎是输出0,所以这里L初始化为1
for(int i=0;i<n;i++) {
scanf("%d%d",&w[i],&e[i]);
L=max(L,max(w[i],e[i]));
R+=max(w[i],e[i]);
}
int ans=1;
while(L<=R) {
int mid=(L+R)>>1;
if(check(mid)) ans=mid,R=mid-1;
else L=mid+1;
}
printf("%d\n",ans-1);//二分的答案是飞机数量 ans要减去1
}
return 0;
}