UVa 1450 - Airport

传送门

UVa 1450 - Airport

题意

有两个方向的飞机要起飞,一次只能飞一架,求任意时刻飞机最大编号的最小值。

思路

大家应该都能想到二分,但是验证的时候有一些要注意。

总的思路就是先储存着飞的飞机,如果有哪一方的飞机数大于mid了,让它飞,之后判断是不是都小于mid。

有一些情况:

  1. 某一时刻储存着的飞机不能多于目前的飞机总数。因为这时候可以飞完全部的飞机,不能继续飞了,也就不能存了。

  2. 当某一时刻有一方的飞机数为0的时候,另一方必须飞!如果这时候也存一下的话,可能把不能飞的飞机也算在了可以飞上面。

代码

#include <bits/stdc++.h>
#define LL long long
#define lowbit(x) ((x) & (-x))
#define MP(a, b) make_pair(a, b)
const int MAXN = 5000 + 5;
const int INF = 0x3f3f3f3f;
using namespace std;
 
struct POINT
{
    int x, y;
}pit[MAXN];
 
int n;
 
bool Check(int mid)
{
    int asum = 0, bsum = 0;
    int rem = 0;
    for (int i = 1; i <= n; i++)
    {
        asum += pit[i].x, bsum += pit[i].y;
        if (asum > mid)
        {
            int t = min(rem, asum - mid);
            rem -= t, asum -= t;
        }
        if (bsum > mid)
        {
            int t = min(rem, bsum - mid);
            rem -= t, bsum -= t;
        }
        if (asum > mid || bsum > mid) return false;
        if (asum && !bsum) asum--;
        else if (bsum && !asum) bsum--;
        else if (asum && bsum && asum + bsum > rem) rem++;
    }
    return true;
}
 
int main()
{
    //freopen("input.txt", "r", stdin);
    int T, i, j;
    scanf("%d", &T);
    while (T--)
    {
        int l = INF, r = 0;
        scanf("%d", &n);
        for (i = 1; i <= n; i++)
        {
            scanf("%d%d", &pit[i].x, &pit[i].y);
            r += pit[i].x + pit[i].y;
        }
        int mid;
        l = 1;
        while (l < r)
        {
            mid = l + ((r - l) >> 1);
            if (Check(mid)) r = mid;
            else l = mid + 1;
        }
        printf("%d\n", l - 1);
    }
    return 0;
}

Powered by Jekyll and Theme by solid