題目鏈接:UVA 7261(A)
題意:在二維座標系第一象限中,將一塊頂點在原點邊長爲R的正方形土地用直線x=n一分爲二,左側分給Wei,右側分給Huo。
土地中包含N個綠洲,每個綠洲是一個矩形,其位置和大小用四元組(L,T,W,H)表示,其中(L,T)爲其左上方頂點的座標,W,H爲其寬度和高度。綠洲互不重疊。
求滿足以下條件的一條劃分直線(直線方程 x=n,0<=n<=R,n取整數):
(1)二人各自所得土地中綠洲面積應滿足Wei>=Huo 且二者之差達到最小;
(2)在滿足(1)的基礎上,Wei的土地面積越大越好。
題解:二分(線性掃描也可以)。
我把L排了個序,而且用dp[i]標記了x = i這條線左邊有多少個綠洲,方便自己計算線x = i左邊的綠洲面積,這個代碼寫的累贅了,跑了123ms。可以不需要這些東西,具體讀者可以參考別人的博客,可能跑的要快幾十ms。
關鍵是二分,這是大家都一樣的。需要兩個二分,第一個二分得到l,目標是得到 線左綠洲面積剛好 >= 線右綠洲面積 時的 綠洲面積;第二個二分,在第一個基礎上,使得r儘可能大,且線左綠洲面積不增加,r即爲答案。
#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#define Max(a,b) a>b?a:b
#define Min(a,b) a>b?b:a
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
int dir[4][2]= {{1,0},{-1,0},{0,1},{0,-1}};
const double eps = 1e-6;
const double Pi = acos(-1.0);
const int INF=0x3f3f3f3f;
const int maxn = 1e6+10;
ll sum,R,summ;
int dp[maxn];
struct Oasis{
ll L,T,W,H;
Oasis(){}
Oasis(ll l,ll t,ll w,ll h): L(l),T(t),W(w),H(h){}
bool operator < (const Oasis &cmp) const {
return L < cmp.L;
}
}arr[maxn];
ll calcu(ll ind){
ll summ = 0;
for(int i = 0; i < dp[ind]; i++){
if(ind < arr[i].L+arr[i].W){
summ += (ind - arr[i].L) * arr[i].H;
}else{
summ += arr[i].W * arr[i].H;
}
}
return summ;
}
ll solve(){
ll l = 0, r = R, mid;
ll summ1,summ2;
while(l <= r){
mid = (l + r) / 2;
summ1 = calcu(mid);
if(summ1 < sum - summ1){
l = mid + 1;
}else{
r = mid - 1;
}
}
ll tmp = calcu(l);
l = 0, r = R;
while(l <= r){
mid = (l + r) / 2;
if(calcu(mid) > tmp){
r = mid - 1;
}else{
l = mid + 1;
}
}
return r;
}
int main(){
int T,n,cnt;
ll l,t,w,h;
// freopen("F://duipai//data.txt","r",stdin);
// freopen("F://duipai//out2.txt","w",stdout);
scanf("%d",&T);
while(T--){
mem(dp,0);
mem(arr,0);
sum = 0;
scanf("%lld",&R);
scanf("%d",&n);
for(int i = 0;i < n; i++){
scanf("%lld%lld%lld%lld",&l,&t,&w,&h);
arr[i] = Oasis(l,t,w,h);
dp[l]++;
sum = sum + w*h;
}
for(int i = 1; i < maxn; i++){
dp[i] = dp[i] + dp[i-1];
}
sort(arr,arr+n);
ll ans = solve();
if(ans > R){
ans = R;
}
printf("%lld\n",ans);
}
return 0;
}