7-2 部落冲突

在一个神秘的岛屿上,有两个部落 A 和 B,部落 A 和 B 之间有一片平原。这片平原上有许多的绿洲,每个绿洲可以看做一个矩形,其边平行于坐标轴。为了避免部落之间的冲突,他们需要在平原上划定一个界线来平均分配这些绿洲。岛屿上的酋长决定让你来帮助他们找到一个公平的划分方法。

具体来说,酋长想要你将这片平原分成两部分,分别归属于部落 A 和 B。划分的界线需要平行于 y 轴,并且可以通过坐标轴上的一个整数点来确定。具体来说,如果界线通过整数点 x,则所有在 x 左边的土地归属于部落 A,所有在 x 右边的土地归属于部落 B。划分的要求如下:

  1. 两部分的绿洲面积尽可能接近。

  2. 部落 A 的绿洲面积应该不小于部落 B 的绿洲面积

现在,请你求出岛屿的分界线x因该在那里,以此来避免部落冲突。

输入格式:

第一行是一个正整数 n,表示这片平原上有 n 个绿洲。 接下来 n 行,每行描述一个绿洲,包含 4 个整数 x, y, w, h,表示这个绿洲的左上角坐标为 (x, y),宽度为 w,高度为 h。保证所有绿洲不会重叠,且所有的坐标、宽度、高度都不超过 1,000,000。

数据范围(1<=n<=100)

输出格式:

对于每组测试数据,输出一个整数 x,表示划分界线的坐标应该为 x。

输入样例:

在这里给出一组输入。例如:

1
0 0 100 100

输出样例:

在这里给出相应的输出。例如:

50
#include<iostream>
using namespace std;
typedef long long ll;
struct rect{
    ll x,y;
    ll w,h;
};
const int N = 110;
rect a[N];
int n;
ll s;
ll sl,sr;
ll get_area(rect &a,ll t){
    if(a.x+a.w<=t)return a.w*a.h;
    else if(a.x+a.w>t&&a.x<=t) return a.h*(t-a.x);
    return 0;
}
ll get_left(ll t){
    ll res=0;
    for(int i=0;i<n;i++)res+=get_area(a[i],t);
    return res;
}


int bin_search(ll l,ll r){
    ll i=l-1,j=r+1;
    while(i<j){
        ll mid = (i+j)>>1;
        sl = get_left(mid);
        sr = s-sl;
        if(sl>=sr)j=mid;
        else i=mid+1;
    }
    return j;
}


int main()
{
    ll l,r;
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>a[i].x>>a[i].y>>a[i].w>>a[i].h;
    }
    l=a[0].x;
    r=a[0].x+a[0].w;
    for(int i=0;i<n;i++){
        s+=a[i].w*a[i].h;
        r = r<a[i].x+a[i].w?a[i].x+a[i].w:r;
        l = l>a[i].x?a[i].x:l;
    }
    cout<<bin_search(l,r);
}

 唯一要注意的就是数据的范围,要用long long而不能用int。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值