CodeForces - 589F

Gourmet and Banquet

Time limit : 2000 msMemory limit : 524288 kB

description:

A gourmet came into the banquet hall, where the cooks suggested n dishes for guests. The gourmet knows the schedule: when each of the dishes will be served.

For i-th of the dishes he knows two integer moments in time ai and bi (in seconds from the beginning of the banquet) — when the cooks will bring the i-th dish into the hall and when they will carry it out (ai < bi). For example, if ai = 10 and bi = 11, then the i-th dish is available for eating during one second.

The dishes come in very large quantities, so it is guaranteed that as long as the dish is available for eating (i. e. while it is in the hall) it cannot run out.

The gourmet wants to try each of the n dishes and not to offend any of the cooks. Because of that the gourmet wants to eat each of the dishes for the same amount of time. During eating the gourmet can instantly switch between the dishes. Switching between dishes is allowed for him only at integer moments in time. The gourmet can eat no more than one dish simultaneously. It is allowed to return to a dish after eating any other dishes.

The gourmet wants to eat as long as possible on the banquet without violating any conditions described above. Can you help him and find out the maximum total time he can eat the dishes on the banquet?

Input

The first line of input contains an integer n (1 ≤ n ≤ 100) — the number of dishes on the banquet.
The following n lines contain information about availability of the dishes. The i-th line contains two integers ai and bi (0 ≤ ai < bi ≤ 10000) — the moments in time when the i-th dish becomes available for eating and when the i-th dish is taken away from the hall.

Output

Output should contain the only integer — the maximum total time the gourmet can eat the dishes on the banquet.
The gourmet can instantly switch between the dishes but only at integer moments in time. It is allowed to return to a dish after eating any other dishes. Also in every moment in time he can eat no more than one dish.

Examples

input
3
2 4
1 5
6 9
output
6

input
3
1 2
1 2
1 2
output
0

Note:

In the first example the gourmet eats the second dish for one second (from the moment in time 1 to the moment in time 2), then he eats the first dish for two seconds (from 2 to 4), then he returns to the second dish for one second (from 4 to 5). After that he eats the third dish for two seconds (from 6 to 8).

In the second example the gourmet cannot eat each dish for at least one second because there are three dishes but they are available for only one second (from 1 to 2).


题目大意:
有一个人去宴会厅品尝各道菜肴,他在每道菜上面花费相同的时间。不过每道菜的开放时间有限,有各自的开始时间与结束时间。
如果不考虑从一道菜到另一道菜的时间,问这个人最多能花多久时间。

解题思路:
1.用二分搜索的方式,去枚举每道菜最多能品尝多久,最大的总时间就是每道菜花费的时间乘以菜的数量。
2.采取贪心策略,优先去品尝结束时间早的,结束时间相同的优先品尝开始时间晚的。

struct Node {
    int start, end;
    bool operator < (const Node& n) const   {
        return end < n.end || ((end == n.end) && (start < n.start));
    }
};

3.将所有的时间看成一段一段的单位时间,用一个bool数组表示这个单位时间有没有在品尝其他菜。按照之前的贪心策略依次去品尝
菜肴。在菜肴开放的时间内依次选取空闲的时间,如果遍历完开放时间,发现能选取的时间没能超过mid,则mid值过大不可行。

核心代码:

bool test(int x) {
    memset(visit, 0, sizeof(visit));      //测试前,先将时间段全部置为空闲
    int fin;
    for (int i = 0; i < num; i++) {
        fin = 0;
        for (int j = q[i].start; j < q[i].end; j++) {
            if (!visit[j]) {
                visit[j] = 1;
                if (++fin == x)            //已经选够了时间,进入下一道菜
                    break;
            }
        }
        if (fin < x)                        //遍历完菜肴的全部开放时间,没有足够时间,x值过大。
            return false;
    }
    return true;
}

4.选取了足够多的时间,达到mid后立刻跳出,进入下一道菜的测试。直到所有的菜都通过测试,则mid值可行。


源代码

#include<iostream>
#include<stdio.h>
#include<vector>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<sstream>
using namespace std;

struct Node {
    int start, end;
    bool operator < (const Node& n) const   {
        return end < n.end || ((end == n.end) && (start < n.start));
    }
};
Node q[10005];
bool visit[10005];
int num;

bool test(int x) {
    memset(visit, 0, sizeof(visit));
    int fin;
    for (int i = 0; i < num; i++) {
        fin = 0;
        for (int j = q[i].start; j < q[i].end; j++) {
            if (!visit[j]) {
                visit[j] = 1;
                if (++fin == x)
                    break;
            }
        }
        if (fin < x)
            return false;
    }
    return true;
}

 int main() {
     int i;
     scanf("%d", &num);
     for (i = 0; i < num; i++) {
         scanf("%d%d", &q[i].start, &q[i].end);
     }
     sort(q, q + num);
     int l = 1, r = 100001;
     while (l<r - 1)     {
         int mid = (l + r) >> 1;
         if (test(mid))
             l = mid;
         else  
             r = mid;
     }
     if (test(l))
         printf("%d\n", l*num);
     else
         printf("0\n");
     return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值