机场(Airport,Seoul 2009,LA 4725)

9 篇文章 0 订阅

AC通道( Uva ):
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4196

PDF https://uva.onlinejudge.org/external/14/1450.pdf


机场


Description

有一个客流量巨大的机场,却只有一条起飞跑道。

这里写图片描述

换句话说,每个时刻只能有一架飞机起飞(从 E 或者 W 通道进入起飞跑道),每个时刻也都有一些飞机到达 E 或者 W 通道中。
在任一时刻, E 通道和 W 通道里的飞机分别从 0 开始编号。
(上图中, E 通道里的飞机编号为 0 1 W 通道里的飞机编号为 0,1,2
你的任务是在每个时刻选择一架飞机起飞,使得任意时刻飞机的最大编号最小。


Input

输入的第一行为数据组数 T
每组数据的第一行为时刻总数 n 1n5000 );
以下 n 行每行两个整数 ai bi 0ai,bi20 ),分别是该时刻到达 W 通道和 E 通道的飞机数量。


Output

对于每组数据,输出飞机最大编号的最小值。


Sample Input

3
1
1 1
3
3 2
0 3
2 0
6
0 1
1 1
1 2
1 1
1 1
6 0


Output

0
3
5


Solution

显然二分答案。

现在就只需要解决判定性问题了。

即当这个最大编号为 x 时,满不满足条件。

因为题目中说,在一个时刻中,起飞一辆飞机。
我们无法判断到底是起飞哪个通道的飞机。

如果某个通道里面的飞机个数为 0,那么自然不能起飞它的飞机。

如果两个通道里面的飞机个数都不为 0 ,我们就先记下,这里起飞了一架飞机。

设起飞飞机 m 个。

某一时刻,某个通道里面的飞机数如果大于了 x ,我们就要将它的飞机数改为 x

a 表示 E 通道里面的飞机数, b 表示 W 通道里面的飞机数。

Max{ax0}+Max{bx0}>m OR ai>x OR bi>x ,则不可能。

a=0 b0 时, b 减一(起飞一个飞机)。

否则,当 a0 b=0 时, a 减一(起飞一个飞机)。

否则,当 a+b>m 时,即两个通道里面的飞机数之和比已经起飞的飞机数大,那么就可以判断出两个通道里面的飞机个数都不为 0 m 加一。


Code

[cpp]
  1. #include <iostream>  
  2. #include <cstdio>  
  3.   
  4. using namespace std;  
  5.   
  6. int T,n;  
  7. int e[5010],w[5010];  
  8.   
  9. inline int mabs(int x){  
  10.     return x<0?0:x;   
  11. }  
  12.   
  13. inline int in(){  
  14.     int ans=0;char x=getchar();  
  15.     while(x<‘0’||x>‘9’)x=getchar();  
  16.     while(x>=‘0’&&x<=‘9’){ans=ans*10+x-‘0’;x=getchar();}  
  17.     return ans;   
  18. }  
  19.   
  20. bool pan(int x){  
  21.     int ss=0,ll=0,rr=0;  
  22.     for(int i=1;i<=n;i++){  
  23.         ll+=e[i];rr+=w[i];  
  24.         if(e[i]>x||w[i]>x)return false;  
  25.         if(mabs(ll-x)+mabs(rr-x)>ss)return false;  
  26.         if(!ll&&rr)rr–;  
  27.         else if(ll&&!rr)ll–;  
  28.         else if(ll+rr>ss)ss++;  
  29.     }  
  30.     return true;  
  31. }  
  32.   
  33. int main(){  
  34.     scanf(”%d”,&T);  
  35.     while(T–){  
  36.         scanf(”%d”,&n);  
  37.         for(int i=1;i<=n;i++){e[i]=in();w[i]=in();}  
  38.         int l=1,r=100000;  
  39.         int ans=r;  
  40.         while(l<=r){  
  41.             int mid=(l+r)/2;  
  42.             bool flag=pan(mid);  
  43.             if(flag){  
  44.                 if(ans>mid)ans=mid;  
  45.                 if(r!=mid-1)r=mid-1;  
  46.                 else break;   
  47.             }  
  48.             else{  
  49.                 if(l!=mid+1)l=mid+1;  
  50.                 else break;   
  51.             }  
  52.         }  
  53.         printf(”%d\n”,ans-1);  
  54.     }  
  55.     return 0;   
  56. }  
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值