在一个神秘的岛屿上,有两个部落 A 和 B,部落 A 和 B 之间有一片平原。这片平原上有许多的绿洲,每个绿洲可以看做一个矩形,其边平行于坐标轴。为了避免部落之间的冲突,他们需要在平原上划定一个界线来平均分配这些绿洲。岛屿上的酋长决定让你来帮助他们找到一个公平的划分方法。
具体来说,酋长想要你将这片平原分成两部分,分别归属于部落 A 和 B。划分的界线需要平行于 y 轴,并且可以通过坐标轴上的一个整数点来确定。具体来说,如果界线通过整数点 x,则所有在 x 左边的土地归属于部落 A,所有在 x 右边的土地归属于部落 B。划分的要求如下:
-
两部分的绿洲面积尽可能接近。
-
部落 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。