- guochaoyou's blog
EXJ1004. 机场设施使用优化 (目前最优解)
- 2023-6-4 8:03:12 @
#EXJ1004. 机场设施使用优化
ID: 255传统题2000ms512MiB尝试: 3已通过: 1难度: 10
机场设施使用优化
时间限制: 1000 ms 内存限制: 524288 KB
【题目描述】
当一架飞机抵达机场时,可以停靠在航站楼旁的廊桥,也可以停靠在位于机场边缘的远机位。乘客一般更期待停靠在廊桥,因为这样省去了坐摆渡车前往航站楼的周折。
然而,因为廊桥的数量有限,所以这样的愿望不总是能实现。
机场分为国内区和国际区,国内航班飞机只能停靠在国内区,国际航班飞机只能停靠在国际区。一部分廊桥属于国内区,其余的廊桥属于国际区。
L 市新建了一座机场,一共有 nn 个廊桥。该机场决定,廊桥的使用遵循“先到先得”
的原则,即每架飞机抵达后,如果相应的区(国内/国际)还有空闲的廊桥,就停靠在廊桥,否则停靠在远机位(假设远机位的数量充足)。该机场只有一条跑道,因此不存在两架飞机同时抵达的情况。
现给定未来一段时间飞机的抵达、离开时刻,请你负责将 nn 个廊桥分配给国内区和国际区,使停靠廊桥的飞机数量最多。
【输入】
输入的第一行包含 33 个正整数 nn, m_1m1, m_2m2 分别表示廊桥的个数、国内航班飞机的数量、国际航班飞机的数量。
接下来 m_1m1 行是国内航班的信息,第 ii 行包含 22 个正整数 a_{1,i}a1**,i**, b_{1,i}b1**,i**,分别表示一架国内航班飞机的抵达、离开时刻。
接下来 m_2m2 行是国际航班的信息,第 ii 行包含 22 个正整数 a_{2,i}a2**,i**, b_{2,i}b2**,i**,分别表示一架国际航班飞机的抵达、离开时刻。
每行的多个整数由空格分隔。
【输出】
输出一个正整数,表示能够停靠廊桥的飞机数量的最大值。
【输入样例】
3 5 4
1 5
3 8
6 10
9 14
13 18
2 11
4 15
7 17
12 16
【输出样例】
7
【提示】
【样例 1 解释】
在图中,我们用抵达、离开时刻的数对来代表一架飞机,如 (11, 55) 表示时刻 11 抵达、时刻 55 离开的飞机;用 √√ 表示该飞机停靠在廊桥,用 ××表示该飞机停靠在远机位。
我们以表格中阴影部分的计算方式为例,说明该表的含义。在这一部分中,国际区有 22 个廊桥,44 架国际航班飞机依如下次序抵达:13135991056次航班
- 首先 (22, 1111) 在时刻 22 抵达,停靠在廊桥
- 然后 (44, 1515) 在时刻 44 抵达,停靠在另一个廊桥
- 接着 (77, 1717) 在时刻 77 抵达,这时前 22 架飞机都还没离开、都还占用着廊桥,而国际区只有 22 个廊桥,所以只能停靠远机位
- 最后 (1212, 1616) 在时刻 1212 抵达,这时 (22,1111) 这架飞机已经离开,所以有 11 个空闲的廊桥,该飞机可以停廊桥
根据表格中的计算结果,当国内区分配 22 个廊桥、国际区分配 11 个廊桥时,停靠廊桥的飞机数量最多,一共 235 架。
【样例 2 输入】
2 4 6
20 30
40 50
21 22
41 42
1 19
2 18
3 4
5 6
7 8
9 10
【样例 2 输出】
4
【样例 2 解释】
当国内区分配 22 个廊桥、国际区分配 00 个廊桥时,停靠廊桥的飞机数量最多,一共44 架,即所有的国内航班飞机都能停靠在廊桥。
需要注意的是,本题中廊桥的使用遵循“先到先得”的原则,如果国际区只有 11 个廊桥,那么将被飞机 (11, 1919) 占用,而不会被 (33, 44)、(55, 66)、(77, 88)、(99, 1010) 这44 架飞机先后使用。
【数据范围】
对于 20% 的数据,1 ≤ n ≤ 1001≤n≤100, 1 ≤ m_1 + m_2 ≤ 1001≤m1+m2≤100。
对于 40% 的数据,1 ≤ n ≤ 50001≤n≤5000, 1 ≤ m_1 + m_2 ≤ 50001≤m1+m2≤5000。
对于 100% 的数据,1 ≤ n ≤ 1000001≤n≤100000, 1 ≤ m_1 + m_2 ≤ 1000001≤m1+m2≤100000。
所有 a_{1,i}a1**,i**, b_{1,i}b1**,i**, a_{2,i}a2**,i**, b_{2,i}b2**,i** 为数值不超过 10^8108 的互不相同的正整数。
保证 ∀_i ∈ [1, n]∀i∈**[1,n], a_{1,i} < b_{1,i}, a_{2,i} < b_{2,i}a1,i**<b1**,i**,a2**,i**<b2**,i**。
本题目评测默认开启-O2−O2。
进入正题(上代码)
代码如下,这边建议不要直接抄袭,可以借鉴 注解在代码中展示
第一种AC:95%,错误一个测试点
#include<set>
#include<cstdio>
#include<algorithm>
#define db double
#define U unsigned
#define ll long long
#define lb long double
#define ull unsigned long long
#define Me(a,b) memset(a,b,sizeof(a))
template<typename _T> _T abs(_T a){ return a>0?a:-a; }
template<typename _T> _T max(_T a,_T b){ return a>b?a:b; }
template<typename _T> _T min(_T a,_T b){ return a<b?a:b; }
template<typename _T> void print(_T x){ if(x<0) putchar('-'),x=-x;
if(x>9) print(x/10); putchar(x%10+48); return; }
#define EPS (1e-7)
#define INF (0x7fffffff)
#define LLINF (0x7fffffffffffffff)
#define maxn 100039
#define maxm
#define MOD
using namespace std;
#define Type int
Type read(){
char c=getchar(); Type sum=0; int flag=0;
while((c<'0'||c>'9')&&c!='-') c=getchar(); if(c=='-') c=getchar(),flag=1;
while('0'<=c&&c<='9'){ sum=(sum<<1)+(sum<<3)+(c^48); c=getchar(); }
if(flag) return -sum; return sum;
}
int n,m1,m2,f1[maxn],f2[maxn];
struct Plane{
int st,en,num;
bool operator < (const Plane x) const{ return this->st < x.st; }
}a1[maxn],a2[maxn];
int cmp(Plane x,Plane y){ return x.st<y.st; }
set<Plane> s; int flag[maxn];
void init(Plane a[],int f[],int m){
s.clear(); int i,now=0; Plane tmp; set<Plane>::iterator it; for(i=1;i<=m;i++) s.insert(a[i]);
while(!s.empty()){
tmp=*s.begin(); s.erase(s.begin()); now++; f[now]=1;
while(1){
tmp.st=tmp.en; it=s.upper_bound(tmp);
if(it==s.end()) break; f[now]++; s.erase(it); tmp=*it;
}
} return;
}
int maxx;
int main(){
//freopen("airport.in","r",stdin);
//freopen(".out","w",stdout);
n=read(); m1=read(); m2=read(); int i;
for(i=1;i<=m1;i++) a1[i].st=read(),a1[i].en=read(),a1[i].num=i; init(a1,f1,m1);
for(i=1;i<=m2;i++) a2[i].st=read(),a2[i].en=read(),a2[i].num=i; init(a2,f2,m2);
//for(i=1;i<=m1;i++) print(f1[i]),putchar(' '); putchar('\n');
//for(i=1;i<=m1;i++) print(f2[i]),putchar(' '); putchar('\n');
for(i=1;i<=m1;i++) f1[i]+=f1[i-1]; for(i=1;i<=m2;i++) f2[i]+=f2[i-1];
for(i=0;i<=n;i++) if(f1[i]+f2[n-i]>maxx) maxx=f1[i]+f2[n-i];
print(maxx); return 0;
}
换种思路重新定义 AC:100%(accept)
#include <bits/stdc++.h>
#include <cstdio>
#include <functional>
#define P pair <int,int>
using namespace std;
struct node {
int a, b;
} fc[100010], fa[100010];
bool cmp(node a, node b) {
return a.a < b.a;
}
int n, m1, m2, maxn = -1, ans1[100010], ans2[100010];
void check() {
priority_queue<int, vector<int>, greater<int> > q;//维护廊桥编号
priority_queue<P, vector<P>, greater<P> > p;//维护飞机出站时间和停靠的廊桥的编号
for (int i = 1; i <= n; i++) {
q.push(i);//一开始所有廊桥都处于空闲状态,把所有廊桥加入队列。
}
for (int i = 1; i <= m1; i++) {
int s = fc[i].a;//该架飞机入站时间
while (!p.empty() && s > p.top().first) {
//弹出已经飞走的飞机并把它所停课的廊桥加入队列
q.push(p.top().second);
p.pop();
}
if (!q.empty()) {
int id = q.top();
q.pop();//取编号最小的廊桥停靠
ans1[id]++;//该编号的廊桥产生的贡献加一
p.push(P(fc[i].b, id));
}
}
while (!q.empty())
q.pop();
while (!p.empty())
p.pop();
//清空队列
for (int i = 1; i <= n; i++) {
q.push(i);
}
//同上
for (int i = 1; i <= m2; i++) {
int s = fa[i].a;
while (!p.empty() && s > p.top().first) {
q.push(p.top().second);
p.pop();
}
if (!q.empty()) {
int id = q.top();
q.pop();
ans2[id]++;
p.push(P(fa[i].b, id));
}
}
for (int i = 1; i <= n; i++) {
ans1[i] += ans1[i - 1];
ans2[i] += ans2[i - 1];
}
//前缀和数组维护每种分配方案产生的答案
return;
}
int main() {
scanf("%d%d%d", &n, &m1, &m2);
for (int i = 1; i <= m1; i++) {
scanf("%d%d", &fc[i].a, &fc[i].b);
}
for (int i = 1; i <= m2; i++) {
scanf("%d%d", &fa[i].a, &fa[i].b);
}
sort(fc + 1, fc + 1 + m1, cmp);
sort(fa + 1, fa + 1 + m2, cmp);
check();
//统计答案
for (int i = 0; i <= n; i++) {
if (ans1[i] + ans2[n - i] > maxn) {
maxn = ans1[i] + ans2[n - i];
}
}
printf("%d", maxn);
return 0;
}