UVALive7261(2015ACM/ICPC北京赛区现场赛A)

题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=5273

思路:二分枚举x。

#include <cstdio>
using namespace std;
const int MAXN = 10005;
typedef long long LL;
struct Rectangle{
    int l, t, w, h;
    LL area;
}rect[MAXN];
int R, n;
LL sum;
LL getArea(int x)
{
    LL ret = 0;
    for(int i = 0; i < n; i++)
    {
        if(rect[i].l+rect[i].w <= x)
        {
            ret += rect[i].area;
        }
        else if(rect[i].l < x)
        {
            ret += ((LL)(x - rect[i].l) * rect[i].h);
        }
    }
    return ret;
}
int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        sum = 0;
        scanf("%d %d", &R, &n);
        for(int i = 0; i < n; i++)
        {
            scanf("%d %d %d %d", &rect[i].l, &rect[i].t, &rect[i].w, &rect[i].h);
            rect[i].area = ((LL)rect[i].w * rect[i].h);
            sum += rect[i].area;
        }
        if(sum == 0)
        {
            printf("%d\n", R);
            continue;
        }
        //尽可能使x两边的oases的面积之和相等
        int left = -1, right = R;//求right.将right初始化为可能的答案,left初始化为取不到的数值.
        while(right - left > 1)
        {
            int mid = (left + right) >> 1;
            LL sl = getArea(mid);
            LL sr = sum - sl;
            if(sl >= sr)
            {
                right = mid;
            }
            else
            {
                left = mid;
            }
        }
        
        //尽可能使x靠右
        int s = getArea(right);
        left = right, right = R+1;//求left.将left去初始化为可能的答案,将right初始化为取不到的答案.
        while(right - left > 1)
        {
            int mid = (left + right) >> 1;
            if(getArea(mid) <= s)
            {
                left = mid;
            }
            else
            {
                right = mid;
            }
        }
        printf("%d\n", left);
    }
    return 0;
}

 二分答案的过程中左右区间的划分问题。大于等于答案的最左值 mid = (left + right) >> 1; 小于等于答案的最右值 mid = (left + right + 1) >> 1;

#include <cstdio>
using namespace std;
const int MAXN = 10005;
typedef long long LL;
struct Rect{
    int l, t, w, h;
}rect[MAXN];
int n, R;
LL sum;
LL getArea(int x)
{
    LL area = 0;
    for(int i = 0; i < n; i++)
    {
        if(rect[i].l + rect[i].w <= x)
        {
            area += ((LL)rect[i].w * rect[i].h);
        }
        else if(rect[i].l < x)
        {
            area += ((LL)rect[i].h * (x - rect[i].l));
        }
    }
    return area;
}
int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        sum = 0;
        scanf("%d %d", &R, &n);
        for(int i = 0; i < n; i++)
        {
            scanf("%d %d %d %d", &rect[i].l, &rect[i].t, &rect[i].w, &rect[i].h);
            sum += ((LL)rect[i].w * rect[i].h);
        }

        int left = 0, right = R;
        while(right > left)
        {
            int mid = (left + right) >> 1; //求大于等于答案的最左值
            LL s1 = getArea(mid);
            LL s2 = sum - s1;
            if(s1 >= s2)
            {
                right = mid;
            }
            else
            {
                left = mid + 1;
            }
        }

        LL tag = getArea(right);
        left = right, right = R;
        while(right > left)
        {
            int mid = (left + right + 1) >> 1; //求小于等于答案的最右值
            if(getArea(mid) <= tag)
            {
                left = mid;
            }
            else
            {
                right = mid - 1;
            }
        }
        printf("%d\n", left);
    }
    return 0;
}

 

posted on 2016-10-22 21:02  vCoders  阅读(247)  评论(0编辑  收藏  举报

导航