zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ", 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
    ", left);
        }
        return 0;
    }
  • 相关阅读:
    jQuery 字符串拼接
    jQuery 筛选器 链式编程操作
    jQuery 常用操作
    jQuery介绍 常用选择器
    枚举-增加BOOL类型
    枚举-判断一年中第 125 天是工作日, 还是休息日?假设一年 365 天, 新年第一天是星期一。
    判断大小端序
    信息存储,共用体的应用
    栈的自实现
    strlen,strcat,strcpy,strcpm 自实现
  • 原文地址:https://www.cnblogs.com/program-ccc/p/5988339.html
Copyright © 2011-2022 走看看