CodeForces 730G Car Repair Shop (优先队列乱搞)

Car Repair Shop
Time Limit: 2000MS Memory Limit: 524288KB 64bit IO Format: %I64d & %I64u
Submit

Status

Description
Polycarp starts his own business. Tomorrow will be the first working day of his car repair shop. For now the car repair shop is very small and only one car can be repaired at a given time.

Polycarp is good at marketing, so he has already collected n requests from clients. The requests are numbered from 1 to n in order they came.

The i-th request is characterized by two values: si — the day when a client wants to start the repair of his car, di — duration (in days) to repair the car. The days are enumerated from 1, the first day is tomorrow, the second day is the day after tomorrow and so on.

Polycarp is making schedule by processing requests in the order from the first to the n-th request. He schedules the i-th request as follows:

If the car repair shop is idle for di days starting from si (si, si + 1, …, si + di - 1), then these days are used to repair a car of the i-th client.
Otherwise, Polycarp finds the first day x (from 1 and further) that there are di subsequent days when no repair is scheduled starting from x. In other words he chooses the smallest positive x that all days x, x + 1, …, x + di - 1 are not scheduled for repair of any car. So, the car of the i-th client will be repaired in the range [x, x + di - 1]. It is possible that the day x when repair is scheduled to start will be less than si.
Given n requests, you are asked to help Polycarp schedule all of them according to the rules above.

Input
The first line contains integer n (1 ≤ n ≤ 200) — the number of requests from clients.

The following n lines contain requests, one request per line. The i-th request is given as the pair of integers si, di (1 ≤ si ≤ 109, 1 ≤ di ≤ 5·106), where si is the preferred time to start repairing the i-th car, di is the number of days to repair the i-th car.

The requests should be processed in the order they are given in the input.

Output
Print n lines. The i-th line should contain two integers — the start day to repair the i-th car and the finish day to repair the i-th car.

Sample Input
Input
3
9 2
7 3
2 4
Output
9 10
1 3
4 7
Input
4
1000000000 1000000
1000000000 1000000
100000000 1000000
1000000000 1000000
Output
1000000000 1000999999
1 1000000
100000000 100999999
1000001 2000000
Source
2016-2017 ACM-ICPC, NEERC, Southern Subregional Contest (Online Mirror, ACM-ICPC Rules, Teams Preferred)

题意就是安排修车。每个修车请求有一个理想开始时间s和一个持续时间d。对于一个请求,如果s<=t<=s+d-1都是空闲的那就直接安排进去。如果不行的话那就找一个开始时间最小的且有d连续间隔的时间进行安排。最后输出每个请求安排后的的开始时间和结束时间。
拿优先队列维护一下,队列里记录的是所有时间段,排序以开始时间为准,开始时间小的排在前。每次从队列里面拿出一个时间段看是否符合,符合的话就把这个时间段切了,分配给当前请求,再把剩下的时间再塞回去。如果最佳开始时间不行那就取队列中第一个连续空闲大于所要求时间的时间段。这里面有些小细节,用两个优先队列维护会比较容易一些。

#include "cstring"
#include "cstdio"
#include "string.h"
#include "iostream"
#include "queue"
#include "vector"
#define MAX 205
int s[MAX],d[MAX];
using namespace std;
typedef struct node
{
    int left,right;
    bool operator()(node &a,node &b)
    {
        return a.left>b.left;
    }
}node;
struct cmp  //优先队列需要的排序函数,升序
{
    bool operator()(node &a,node &b)
    {
        return a.left>b.left;
    }
};

int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        int ans[MAX];
        priority_queue<node,vector<node>,cmp> list1,list2;
        for(int i=1;i<=n;i++)
        {
            scanf("%d %d",&s[i],&d[i]);
        }
        node temp;
        temp.left=1;
        temp.right=1500000000;
        list1.push(temp);
        for(int i=1;i<=n;i++)
        {
            int flag=0;
            while(!list1.empty())
            {
                node now=list1.top();
                list1.pop();
                if(now.left<=s[i]&&(now.right-s[i]+1)>=d[i])
                {
                    flag=1;
                    ans[i]=s[i];
                    node my;
                    my.left=now.left;
                    my.right=s[i]-1;
                    if(my.left<=my.right)
                        list1.push(my);
                    my.left=s[i]+d[i];
                    my.right=now.right;
                    if(my.left<=my.right)
                        list1.push(my);
                    break;
                }
                list2.push(now);
            }
            if(flag==0)
            {
                while(!list2.empty())
                {
                    node now=list2.top();
                    list2.pop();
                    if((now.right-now.left+1)>=d[i])
                    {
                        flag=1;
                        ans[i]=now.left;
                        node my;
                        my.left=now.left+d[i];
                        my.right=now.right;
                        if(my.left<=my.right)
                            list1.push(my);
                        break;
                    }
                    list1.push(now);
                }
            }
            while(!list2.empty())
            {
                node temp=list2.top();
                list2.pop();
                list1.push(temp);
            }
        }
        for(int i=1;i<=n;i++)
        {
            printf("%d %d\n",ans[i],ans[i]+d[i]-1);
        }

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值