1. 程式人生 > >NOI題庫1.11程式設計基礎之二分查詢 矩形分割

NOI題庫1.11程式設計基礎之二分查詢 矩形分割

03:矩形分割

總時間限制: 
1000ms 
記憶體限制: 
65536kB
描述

平面上有一個大矩形,其左下角座標(00),右上角座標(R,R)。大矩形內部包含一些小矩形,小矩形都平行於座標軸且互不重疊。所有矩形的頂點都是整點。要求畫一根平行於y軸的直線x=kk是整數,使得這些小矩形落在直線左邊的面積必須大於等於落在右邊的面積,且兩邊面積之差最小。並且,要使得大矩形在直線左邊的的面積儘可能大。注意:若直線穿過一個小矩形,將會把它切成兩個部分,分屬左右兩側。

輸入
第一行是整數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
思路:
這道題目要用二分查詢,這是肯定的.
那麼在那個地方進行查詢?
就是在找分割線的時候二分這個[1,r]的範圍.
怎麼二分?
就是看這個範圍mid,左邊和右邊之差,找出最小的差即可.
這道題目要用資料的型別是什麼?
所有的變數最好用long long.因為答案會很大.會超.
long long C語言號外:
這個型別比較特殊.而且OJ是linux系統.所以
讀入要用:
C:scanf("%lld");C++:cin>>n
輸出要用:
C:printf("%lld");C++:cout<<n
還有資料用結構體會跟好,因為高寬等等一些因素.
所以我的程式碼使用結構體.
程式碼如下:
#include<stdio.h>
#include<math.h>
#include<iostream>
using namespace std;
struct obj
{
    long long left,top,w,h;
    long long rx;
    long long s;
};
long long sigema(struct obj a[],int n,int mid)
{
    int i;
    long long sum1,sum2;
    sum1=sum2=0;
    for(i=0;i<n;i++)
    {
        if(a[i].rx<=mid) sum1+=a[i].s;
        else if(a[i].left>=mid) sum2+=a[i].s;
        else
        {
            sum1+=a[i].h*(mid-a[i].left);
            sum2+=a[i].h*(a[i].rx-mid);
        }
    }
    return sum1-sum2;
}
int main()
{
    long long r,n,i;
    struct obj a[10005];
    long long minx,maxx,mid,ans,maxx2;
    long long temp,temp1,temp2;

    scanf("%lld%lld",&r,&n);
    for(i=0;i<n;i++)
    {
        scanf("%lld%lld%lld%lld",&a[i].left,&a[i].top,&a[i].w,&a[i].h);
        a[i].s=a[i].w*a[i].h;
        a[i].rx=a[i].left+a[i].w;
        if(i==0)  maxx2=a[i].rx;
        else
        {
            if(a[i].rx>maxx2) maxx2=a[i].rx;
        }
    }
    minx=0;
    maxx=r;
    while(minx+1<maxx)
    {
        mid=(minx+maxx)/2;
        temp=sigema(a,n,mid);
        if(temp>0) maxx=mid;
        else if(temp<=0) minx=mid;
    }
    temp1=sigema(a,n,minx);
    temp2=sigema(a,n,maxx);
    if( temp1<temp2)
    {
        if(temp1>=0) ans=minx;
        else ans=maxx;
    }
    else if(temp1>temp2)
    {
        if(temp2>=0) ans=maxx;
        else ans=minx;
    }
    else ans=maxx;
    if(ans==maxx2) ans=r;
    printf("%lld\n",ans);
    return 0;
}
以上程式碼,是我參照別人的程式碼所總結