Kick Start 2019 Round A Problem C. Contention

10 篇文章 0 订阅
1 篇文章 0 订阅

Round A - Kick Start 2019 Problem C. Contention


C. Contention

题目链接
题面:

You are selling tickets for the front row of seats at a movie theater. The front row has N seats, numbered 1 to N from left to right. You have been out of the office the last week, and upon your return, Q bookings for seats have piled up! The i-th booking requests all the seats from Li to Ri inclusive. You now have the boring job of entering each booking into the system, one at a time.

Since some of the bookings may overlap, the system might not be able to fulfill each booking entirely. When you enter a booking into the system, it will assign every seat requested by the booking that hasn’t already been assigned to a booking entered into the system earlier.

What is the largest integer k where there exists an order that you can enter the bookings into the system, such that each booking is assigned at least k seats?

Input
The first line of the input gives the number of test cases, T. T test cases follow. Each test case starts with a line containing two integers N and Q, the number of seats and the number of bookings, respectively. Then, there are Q more lines, the i-th of which contains the two integers Li and Ri, indicating that the i-th booking would like to book all the seats from Li to Ri, inclusive.

Output
For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is the largest value k, as described above.

Limits
Time limit: 30 seconds per test set.
Memory limit: 1GB.
T = 100.
1 ≤ N ≤ 106.
1 ≤ Li ≤ Ri ≤ N.

Test set 1 (Visible)
1 ≤ Q ≤ 300.

Test set 2 (Hidden)
1 ≤ Q ≤ 30000.
For at least 85 of the test cases, Q ≤ 3000.

Sample

Input

Output

3
5 3
1 2
3 4
2 5
30 3
10 11
10 10
11 11
10 4
1 8
4 5
3 6
2 7

Case #1: 1
Case #2: 0
Case #3: 2

In Sample Case #1, there are N = 5 seats and Q = 3 bookings. One possible order is:
Put in the second booking, where the system will book 2 seats (3 and 4).
Put in the first booking, where the system will book 2 seats (1 and 2).
Put in the third booking, where the system will book 1 seat (only seat 5, since seats 1, 2, 3 and 4 are already booked).
Each booking is assigned at least 1 seat, and there is no order that assigns at least 2 seats to each booking, so the answer is 1.

In Sample Case #2, there are N = 30 seats and Q = 3 bookings. No matter what order you assign the seats in, at least one booking will have no seats assigned to it. So the answer is 0. Notice that there can be seats that are not part of any bookings!

In Sample Case #3, there are N = 10 seats and Q = 4 bookings. One possible order is:
Put in the second booking, where the system will book 2 seats (4 and 5).
Put in the third booking, where the system will book 2 seats (3 and 6, since 4 and 5 are already booked). Notice that the seats booked are not necessarily adjacent to each other.
Put in the fourth booking, where the system will book 2 seats (2 and 7).
Put in the first booking, where the system will book 2 seats (1 and 8).
Each booking is assigned at least 2 seats, and there is no order that assigns at least 3 seats to each booking, so the answer is 2.

Note: We do not recommend using interpreted/slower languages for the Large dataset of this problem.

题意:

有N个座位,编号为1到N。现在有Q个预定,要求遇到 l i l_i li r i r_i ri的座位。当执行第 i i i个预定时,如果某些座位(假设有 a a a个)已经被预定了,那么这次预定有效预定数为 r i − l i + 1 + a r_i-l_i+1+a rili+1+a
这些预定顺序可以任意,要你求所有预定最小预定座位数量的最大值。

思路:

二分。
重点在于判断是否可行阶段。
首先,对于两个预定,它们只有两种执行顺序,a先b后,或b先a后。
现在判断的思路是,
首先根据区间左右端点排序,第一关键字为起始点,第二关键字为 − - 终止点,
要使得这些预定尽可能满足最小值k的需求,每次求得第 i i i个区间满足需求后,最后一个座位后一个座位,设为 e d ed ed
对于两个区间,进行以下讨论:

  • 两个区间相离,无需要进行特别讨论;
  • 两个区间相交,
    • 如果后一个区间起始点在 e d ed ed之后,那么则可以在执行的时候,让后者先执行;
    • 如果后一个区间起始点在 e d ed ed之前,那么只能先将后者起始点偏移到 r i + 1 r_i +1 ri+1,否则第 i i i个区间就满足不了了;
  • 如果前者包含了后者,那么,后者必须先执行,因此在计算前者有效位置的时候,需要跳过后者;

根据上述规则,可以在 O ( Q 2 ) O(Q^2) O(Q2)的时间内完成判断,算法总复杂度为 O ( Q 2 l o g N ) O(Q^2logN) O(Q2logN)

AC代码:
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <stack>
#include <bitset>

using namespace std;

#define FSIO  ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define DEBUG(a)   cout<<"DEBUG: "<<(a)<<endl;
#define ll  long long
#define ull unsigned long long
#define ld long double
#define pb push_back
#define MP make_pair
#define X  first
#define Y  second
#define REP(i,st,ed)    for(int i=st;i<=ed;++i)
#define IREP(i,st,ed)   for(int i=st;i>=ed;--i)
#define TCASE(T)    cin>>T;while(T--)

const int MAXN = 1000005;
const ll MOD = 998244353  ;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const int INF = 1e9+7;
const double PI = acos(-1.0);
const double EPS = 1e-8;

int _;

using namespace std;



int l[MAXN], r[MAXN], bias[MAXN];
int N;
int Q;
int mk[MAXN];
vector<pair<int,int>> book;

int judge(int k)
{
    REP(i,1,Q)  l[i]=book[i-1].X, r[i]=-book[i-1].Y, bias[i]=book[i-1].X;

    REP(i,1,Q)
    {
        int st = bias[i];
        int ed = r[i];
        int cnt = 0;
        REP(j,i+1,Q)
        {
            if(r[j]<=r[i])
            {
                if(l[j]<=st)
                {
                    st = max(r[j]+1,st);
                }
                else
                {
                    cnt += l[j]-st;
                    st = max(st,r[j]+1);
                    if(cnt>=k)
                    {
                        ed = l[j]-(cnt-k);
                        break;
                    }
                }
            }
        }
        if(cnt<k)
        {
            cnt += r[i]-st+1;
            if(cnt<k)   return 0;
            ed = r[i]-(cnt-k)+1;
        }
        REP(j,i+1,Q)
        {
            if(l[j]>=ed)    break;
            if(r[j]>r[i])
            {
                bias[j] = max(bias[j],r[i]+1);
            }
        }
    }
    return 1;
}

int main()
{
    //freopen("test.in","r+",stdin);
    //freopen("test.out","w+",stdout);
    FSIO;
    int T;  cin>>T;
    for(int tt=1;tt<=T;++tt)
    {
        cin>>N>>Q;
        book.clear();
        REP(i,1,Q)
        {
            cin>>l[i]>>r[i];
            book.pb(MP(l[i],-r[i]));
        }
        sort(book.begin(),book.end());
        int L = 0;
        int R = N;
        int ans = -1;
        while(L<=R)
        {
            int mid = (L+R)>>1;
            if(judge(mid))
            {
                ans = mid;
                L = mid+1;
            }
            else
            {
                R = mid-1;
            }
        }

        cout<<"Case #"<<tt<<": "<<ans<<endl;
    }

    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值