The 2015 ACM-ICPC Asia Beijing Regional A.Xiongnu's Land

来源:互联网 发布:eclipse写java程序 编辑:程序博客网 时间:2024/05/29 08:01

题目链接: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;}
阅读全文
0 0