二分 - bailian 4136:矩形分割

###题目链接 http://bailian.openjudge.cn/practice/4136/ ###分析 题目要一条竖线把这些矩形分割,要左边面积大于等于右边面积,两边面积还要尽量接近。这个问法和前面有道题问法很像,前几条博客里有道题说:给一个有序序列,再给一个数,要求输出序列中离这个数最近的数。左边面积等于右边面积,不就是给的这个数在序列中出现了;两边面积尽量接近,就好比在后者问题中给的数在序列没有出现,找出离给的数最近的序列元素。 回到这道题,这个题可以用二分法的原因在于:如果一条线x = k能将小矩形们分为左大右小,那在x = k右边的线一定可以将所有小矩形分为左大右小。分成左小右大的情况也是相似的。 这道题需要注意的一点是,求左右面积差的时候,一定要使用long long类型,int 类型不够保存。 ###解题代码

//
//  main.cpp
//  4136:矩形分割 4136:矩形分割
//
//  Created by apple on 2020/3/30.
//  Copyright © 2020 apple. All rights reserved.
//

#include <cstring>
#include <cstdio>


long long area(int );
int r, n;
struct rectange{
    int l, t, w, h;
}p[10010];

int main(){
    scanf("%d%d", &r, &n);
    for(int i = 0; i < n; i++){
        scanf("%d %d %d %d", &p[i].l, &p[i].t, &p[i].w, &p[i].h);
    }
    int low = 0, high = r, mid;
    while(low <= high){
        mid = low + (high - low) / 2;
        if(area(mid) < 0){
            low = mid + 1;
        }
        else if(area(mid) > 0){
            high = mid - 1;
        }
        else
            break;
    }
    int x = 0;
    if(low <= high)
        x = mid;
    else
        x = low;
    
    while(area(x) == area(x + 1) && x<r)
        x++;
    printf("%d\n", x);
    return 0;
    
}

long long area(int mid){
    long long lsum = 0, rsum = 0;
    for(int i = 0; i < n; i++){
        if(p[i].l + p[i].w <= mid){
            lsum += p[i].w * p[i].h;
        }
        else if(p[i].l >= mid){
            rsum += p[i].w * p[i].h;
        }
        else{
            lsum += p[i].h * (mid - p[i].l);
            rsum += p[i].h * (p[i].l + p[i].w - mid);
        }
    }
    return lsum - rsum;
}

猜你喜欢

转载自www.cnblogs.com/zhangyue123/p/12603524.html