总时间限制:
25000ms
单个测试点时间限制:
1000ms
内存限制:
524288kB
描述
平面上有一个大矩形,其左下角坐标 (0,0),右上角坐标(R,R)。大矩形内部包含一些小矩形,小矩形都平行于坐标轴且互不重叠(允许边界重合)。所有矩形的顶点都是整点。要求画一根平行于 y 轴的直线 x=k(k是整数) ,使得这些小矩形落在直线左边的面积必须大于等于落在右边的面积,且两边面积之差最小。并且,要使得大矩形在直线左边的的面积尽可能大。注意:若直线穿过一个小矩形,将会把它切成两个部分,分属左右两侧。
输入
第一行是整数 R,表示大矩形的右上角坐标是 (R,R) (1<=R<=1,000,000)。
接下来的一行是整数 N,表示一共有 N 个小矩形 (1<=N<=10000)。
再接下来有 N 行。每行有4个整数 L,T,W,H,分别表示一个小矩形的左上角坐标是 (L,T),宽度是W,高度是H (0<=L,T<=R, 1<=W,H<=R)。数据保证小矩形不会有位于大矩形之外的部分,且任意两个小矩形面积不重叠。
输出
输出整数 k,表示答案应该是直线 x=k。如果必要的话,x=R 也可以是答案。
样例输入
样例输入1 1000 2 1 1 2 1 5 1 2 1 样例输入2 5000 3 0 1 1 1 0 100 1 20 0 5000 1 100
样例输出
样例输出1 5 样例输出2 5000
题库里突然多了个数据加强版 两个二分直接AC
代码:
#include <bits/stdc++.h> using namespace std; #define maxn 10005 long long r,n,l[maxn],t[maxn],w[maxn],h[maxn],a; long long getnum(int k){ long long ln=0,cnt; for(int i=1;i<=n;i++){ if(l[i]+w[i]<=k) cnt=w[i]; else if(l[i]<=k) cnt=k-l[i]; else cnt=0; ln+=cnt*h[i]; } return ln; } bool check(int k){ long long l=getnum(k); return l>=a-l; } int main(){ cin>>r>>n; for(int i=1;i<=n;i++){ cin>>l[i]>>t[i]>>w[i]>>h[i]; a+=1ll*w[i]*h[i]; } int l=0,ri=r,mid,k; while(l<=ri){ mid=(l+ri)/2; if(check(mid)) ri=mid-1; else l=mid+1; } int ans=l; int ln=getnum(ans); ri=r; while(l<=ri){ mid=(l+ri)/2; long long k=getnum(mid); if(k==ln){ ans=mid; l=mid+1; } else ri=mid-1; } cout<<ans<<endl; return 0; }