NOI題庫1.11程式設計基礎之二分查詢 矩形分割
阿新 • • 發佈:2019-02-18
03:矩形分割
- 總時間限制:
- 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
-
思路:
-
這道題目要用二分查詢,這是肯定的.
-
那麼在那個地方進行查詢?
-
就是在找分割線的時候二分這個[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; }