多个限制的二分题 poj 矩形分割

openoj 矩形分割

总时间限制:  1000ms  内存限制: 65536kB
描述

平面上有一个大矩形,其左下角坐标(0,0),右上角坐标(R,R)。大矩形内部包含一些小矩形,小矩形都平行于坐标轴且互不重叠。所有矩形的顶点都是整点。要求画一根平行于y轴的直线x=k(k是整数) ,使得这些小矩形落在直线左边的面积必须大于等于落在右边的面积,且两边面积之差最小。并且,要使得大矩形在直线左边的的面积尽可能大。注意:若直线穿过一个小矩形,将会把它切成两个部分,分属左右两侧。

输入
第一行是整数R,表示大矩形的右上角坐标是(R,R) (1 <= R <= 1,000,000)。
接下来的一行是整数N,表示一共有N个小矩形(0 < N <= 10000)。
再接下来有N 行。每行有4个整数,L,T, W 和 H, 表示有一个小矩形的左上角坐标是(L,T),宽度是W,高度是H (0<=L,T <= R, 0 < W,H <= R). 小矩形不会有位于大矩形之外的部分。
输出
输出整数n,表示答案应该是直线 x=n。 如果必要的话,x=R也可以是答案。
样例输入
1000
2
1 1 2 1
5 1 2 1
样例输出
5
大致题意:有一个大矩形中有多个不相交的小矩形,要找一个 x 值使得在 x 左边的小矩形面积  >= 右面积(如果于 x 相切分为两半),并且保证大矩形左面积经可能的大。
思路:很明显这是根据小矩形左面积递增关系进行二分的题,不过这个边界条件比较特殊。分两种情况:
1.存在 == 这时只需要找到 == 的最右值;(二分 <= 最右端值)
2不存在 == 这时二分取到了 < 的最右值 但答案是刚好  > 的最右值;

1 while(l<=r){
2             mid = md;
3             ll ant = fid(mid);//左边小矩形的面积
4             if(ant<vsum-ant) l = mid+1;
5             else r = mid-1;
6         }
7         ll cnt = fid(l);
8         while(cnt==fid(l)&&l<=n) l++;

再聊聊这个二分:这种二分写法参见 博客园 https://www.cnblogs.com/luoxn28/p/5767571.html
他的这种思路就是只考虑二分的最终结果,进而判断二分方向与结束时的取值。
  大致讲一下
  

while(l<=r){
            mid = md;
            ll ant = fid(mid);//左边小矩形的面积
            if(ant<vsum-ant) l = mid+1;//在while中 l 是一直满足这个的 fid(l)<= key
            else r = mid-1;
}//二分结束 l,r 的位置关系变成  r,l 这时 l 刚好不再满足while内的关系 //所以此时 l 刚好 > key 所以 r 为 <= 最右端的值

最后再讲一下这题的坑  long long

和一个偷懒的地方   求小矩形面积的时候提前把总面积求了,二分时只求一半。
下面是我的完整代码

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <queue>
 5 #include <cmath>
 6 #include <map>
 7 #include <set>
 8 #include <algorithm>
 9 #define ll long long
10 #define md l+(r-l>>1)
11 #define max(a,b) (a<b?b:a)
12 #define min(a,b) (a<b?a:b)
13 using namespace std;
14 const int maxn = 1e5+500;
15 struct node{
16     ll L,H,x;
17 }mp[maxn];
18 int n,m;
19 ll vsum;
20 bool cmp(node a,node b){
21     return a.x<b.x;
22 }
23 ll fid(ll t){
24     ll sum = 0;
25     for(int i=0;i<m;++i){
26         if(mp[i].x<t){//左边在
27             if(mp[i].x+mp[i].L<=t) sum+=mp[i].H*mp[i].L;//右边
28             else sum+=mp[i].H*(t-mp[i].x);
29         }
30         else break;
31     }
32     return sum;
33 }
34 int main(){
35     while(~scanf("%d%d",&n,&m)){
36         vsum = 0;int t;
37         for(int i=0;i<m;++i){
38             scanf("%lld%d%lld%lld",&mp[i].x,&t,&mp[i].L,&mp[i].H);
39             vsum += mp[i].L*mp[i].H;
40         }
41         sort(mp,mp+m,cmp);//以小矩形的左纵边x
42         ll l=0,r=n,mid;
43         while(l<=r){
44             mid = md;
45             ll ant = fid(mid);//左边小矩形的面积
46             if(ant<vsum-ant) l = mid+1;
47             else r = mid-1;
48         }
49         ll cnt = fid(l);
50         while(cnt==fid(l)&&l<=n) l++;
51         printf("%d\n",l-1);
52     }
53     return 0;
54 }

原文地址:https://www.cnblogs.com/DeadWooder/p/9526856.html

时间: 2024-11-13 02:48:21

多个限制的二分题 poj 矩形分割的相关文章

【题解整理】二分题

[题解整理]二分题 题目类型: 二分查找: 二分答案. 大致解题思路: 查找注意有序和返回值: 浮点数注意精度: 整数注意返回值,建议另外维护一个变量,用于储存可行解. 题目 分类 传送门 WA点 poj 2785 二分查找 题解 lightoj 1088 二分查找 题解 lightoj 1307 二分查找 题解 longlong poj 2456 整数二分答案 题解 poj 3104 整数二分答案 题解 poj 3258 整数二分答案 题解 poj 3273 整数二分答案 题解 lightoj

字典树模板题 POJ 2503

1 #include <cstdio> 2 #include <cstring> 3 4 char en[11],fr[11]; 5 int st; 6 struct Tire{ 7 int next[26]; 8 char eng[11]; 9 }node[200005]; 10 void insert(char *s,int cur) 11 { 12 if(*s){ 13 if(!node[cur].next[*s-'a']) 14 node[cur].next[*s-'a']

木材加工(裸二分题)(附二分算法粗略介绍)

看到旁边的学弟也在做二分,就手贱2分钟打了一道奇(sha)特(bi)二分题. 原题传送门 好吧,做这道题是为了给新手一个教程 首先我们聊聊二分. 二分利用的也是分治思想 不懂分治思想的可以看看我归并做的那道火柴排队. 传送门 首先要了解一下二分的性质(也就是什么题目要用二分来写.) 我们假设一个题目,如果一个数a能够满足题意,并且U=[数值最小值/数值最大值(看题意)~a]中的数就一定能够满足题意. 那么这道题目就能用来二分.. 或者说一道题目的解的解集为U,如0<i<a;题目的范围是0<

[二分+容斥原理] poj 2773 Happy 2006

题目链接: http://poj.org/problem?id=2773 Happy 2006 Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 9131   Accepted: 3073 Description Two positive integers are said to be relatively prime to each other if the Great Common Divisor (GCD) is 1.

2017.4.23 1.矩形分割

1.矩形分割 (二分) 1000ms 内存限制:  65536kB 描述 平面上有一个大矩形,其左下角坐标(0,0),右上角坐标(R,R).大矩形内部包含一些小矩形,小矩形都平行于坐标轴且互不重叠.所有矩形的顶点都是整点.要求画一根平行于y轴的直线x=k(k是整数) ,使得这些小矩形落在直线左边的面积必须大于等于落在右边的面积,且两边面积之差最小.并且,要使得大矩形在直线左边的的面积尽可能大.注意:若直线穿过一个小矩形,将会把它切成两个部分,分属左右两侧. 输入 第一行是整数R,表示大矩形的右上

hnu12884 Area Coverage 矩形分割 or 线段树

题意:给你n个二维平面上的矩形,可以两两覆盖,问最后覆盖的总面积为多少 解题思路:1)矩形状分割,可以知道,每多出一个矩形就和前面所有产生的矩形判断,看是有相交,如果有的话,就对前面的矩形进行分割,最多可以分割成8块,因为这个算法是n×n的算法时间复杂度,所以我们还需要在枚举的时候加速,采用引导值(下一个不为0的矩阵的值),最后6700ms过了 解题代码: 1 // File Name: rect1.c 2 // Author: darkdream 3 // Created Time: 2014

[Offer收割]编程练习赛12 题目3 : 矩形分割

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi有一块由NxM个单位正方形组成的矩形.现在小Ho在某些单位正方形上画了一道分割线,这条分割线或者是单位正方形的主对角线(用'\'表示),或者是副对角线(用'/'表示). 现在小Hi想知道这些分割线把NxM的矩形分割成了多少块区域. 例如 /\/ 就把2x2的矩形分成了5个区域. /\/\ / \/ 把3x4的矩形分成了7个区域. 输入 第一包含两个整数N和M.(1 <= N, M <= 100) 以下N行每行包

hihoCoder 第253周 hiho一下 矩形分割

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi有一块由NxM个单位正方形组成的矩形.现在小Ho在某些单位正方形上画了一道分割线,这条分割线或者是单位正方形的主对角线(用'\'表示),或者是副对角线(用'/'表示). 现在小Hi想知道这些分割线把NxM的矩形分割成了多少块区域. 例如 /\/ 就把2x2的矩形分成了5个区域. /\/\ / \/ 把3x4的矩形分成了7个区域. 输入 第一包含两个整数N和M.(1 <= N, M <= 100) 以下N行每行包

POJ 8208 矩形分割 【二分】

要使两边面积之差最小且保证小矩形直线左边面积大于等于右边面积,在此基础上使大矩形在直线左边的面积尽量大. 想了想后我把这道题分为两步解决,首先找到面积之差的最小值:然后想到一个范围内划直线都是这个最小值,在这个范围内找到最右边的(即保证大矩形左边的面积最大). 第一次二分算面积之差最小值,square(k)返回x=k这条直线左边小矩形的面积,s是所有小矩形的面积:若square(k)>=s-square(k),那面积差最小就在k的左边(包括k),不然就在k+1右边找. 第二次二分的本质是左右矩形