2015-2016 ACM-ICPC, NEERC, Southern Subregional Contest F. Gourmet and Banquet(贪心+二分)

该题是一道比较典型的贪心+二分,  题目中已经加深提示了吃每个菜的时间要一样, 那么这个时间到底是多少呢?   我们很自然的想到了要用二分来加速算法。

所以主体框架就是二分这个吃每道菜的时间, 然后问题的关键是如何判断到底能不能满足要求。 处理区间问题, 我们可以采取贪心的思想,为了给后续的菜留出尽量多的空间,我们可以按照区间右端点从小到大排序, 但是区间覆盖情况很复杂,所以我们不妨牺牲一些时间,对于每个区间都扫一遍,对于每个时间点,我们用一个数组记录该时间是否访问过,然后就可以在O(1000*n*log(1000))的时间复杂度下求出答案了。

下面我们证明为什么这样的贪心规则是正确的:假如不这样的话, 我们处理的前一个区间的右端点比后一个序列的右端点大, 那么就有可能占据了本该属于后一个区间的位置,这样不会更优, 所以应该尽量先满足右区间小的。

细节参见代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
#define max(a,b) a>b?a:b
#define min(a,b) a<b?a:b
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int INF = 1000000000;
const int maxn = 100+5;
int T,n,vis[10007], cnt = 0;
struct node {
    int a, b;
    node(int aa=0, int bb=0):a(aa), b(bb) {}
    bool operator < (const node& rhs) const {
        return b < rhs.b || (b == rhs.b && a < rhs.a);
    }
}a[maxn];
bool ok(int m) {
    cnt++;
    for(int i = 0; i < n; i++) {
        int cur = 0;
        for(int j = a[i].a; j < a[i].b; j++) {
            if(cur == m) break;
            if(vis[j] != cnt) {
                vis[j] = cnt;
                cur++;
            }

        }
        if(cur < m) return false;
    }
    return true;
}
int main() {
    scanf("%d",&n);
    int minv = INF;
    for(int i=0;i<n;i++) {
        scanf("%d%d",&a[i].a,&a[i].b);
        minv = min(minv, a[i].b - a[i].a);
    }
    sort(a,a+n);
    int l = 0, r = minv, m;
    while(r > l) {
        m = (r+l)/2;
        if(ok(m)) l = m+1;
        else r = m;
    }
    while(!ok(r)) r--;
    printf("%d\n",r*n);
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值