15北京区域赛——A 二分——hihoCoder 1249 Xiongnu's Land

两次二分,第一次取得最小值,第二次往右二分看是否能到更右边

注意超出部分land部分要去掉

#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
struct edge{
    int x, y, w, h;
}a[10010];
bool cmp(edge A, edge B)
{
    return A.x < B.x;
}
int n;
ll cal(int x)
{
    ll S = 0;
    for(int i = 1; i <= n; i++){
        if(a[i].x < x){
            S += 1ll * (min(x, a[i].x + a[i].w) - a[i].x) * min(a[i].h, a[i].y);
        }
    }
    return S;
}

int main()
{
    int T, R;
    scanf("%d", &T);
    while(T--){
        int l, r, mid;
        scanf("%d", &R);
        scanf("%d", &n);
        ll Sum = 0;
 //       max_r = R;
        for(int i = 1; i <= n; i++){
            scanf("%d%d%d%d", &a[i].x, &a[i].y, &a[i].w, &a[i].h);
            Sum += 1ll * min(a[i].h, a[i].y) * min(a[i].w, R - a[i].x);
        }
        sort(a + 1, a + n + 1, cmp);
        l = 0;
        r = R;
        ll S, _S;
        ll f_S = 1e13;
        int ans = R;
        while(l <= r){
            mid = l + r >> 1 ;
            S = cal(mid);
            _S = S - (Sum - S);
           // printf("%d %lld\n", mid, _S);
            if(_S >= 0){
                if( _S <= f_S){
                //printf("%d %d ", l, r);
                r = mid - 1;
                f_S = _S;
                ans = min(ans, mid);
               // printf("%d\n", ans);
                }
                else
                   l = mid + 1;
            }
            else  
                l = mid + 1;
        }
        r = R;
        l = ans;
        while(l <= r){
            mid = l + r >> 1;
            S = cal(mid);
            _S = S - (Sum - S);
            if(_S < f_S) l = mid + 1;
            if(_S == f_S){
                ans = max(ans, mid);
                l = mid + 1;
            }
            else r = mid - 1;
        }
    printf("%d\n", ans);
    }
    return 0;
}

  

posted @ 2015-11-16 21:13  Painting、时光  阅读(155)  评论(0编辑  收藏  举报