写篇题解来纪念我炸掉的CSP

唯一会做的题代码写挂了(痛苦面具

思路

我看到这道题第一眼想到的是线段树,感觉可以用线段树维护飞机入站到出战的这段时间,想了半天想不到代码怎么写。

国内机场与国外机场要分开计算

突然发现可以用一个优先队列来维护飞机出站的时间,给每架飞机按入站时间排好序后可以从小到大依次让飞机入站,并比较此时是否有飞机出站,有就把队首元素弹出。

40 pts

可以暴力枚举每一种国内机场和国际机场廊桥的分配方案。

代码如下:

#include <bits/stdc++.h>
#include <functional>
#define N 100010
using namespace std; struct node {
int a, b;
} fa[N], fc[N];//分别为国外机场航班和国内机场航班
int n, m1, m2, _ans; bool cmp(node a, node b) {
return a.a < b.a;
} void check(int ans) {//ans表示国内机场分配的廊桥数
priority_queue <int, vector<int>, greater<int> > q;
int res = 0;
for (int i = 1; i <= m1; i++) {
int s = fc[i].a;
while (!q.empty() && s > q.top()) {
q.pop();//弹出已经出站的飞机
}
if (q.size() < ans) {
q.push(fc[i].b);//如果有空余的廊桥就加入廊桥
res++;//答案+1
}
} while (!q.empty())
q.pop();//清空队列元素 for (int i = 1; i <= m2; i++) {
int s = fa[i].a;
while (!q.empty() && s > q.top()) {
q.pop();
}
if (q.size() < n - ans) {//n-ans表示国外机场分配的廊桥数
q.push(fa[i].b);//同上
res++;
}
}
_ans = max(_ans, res);
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);//按入站时间排序 for (int i = 0; i <= n; i++) {
check(i);//暴力枚举统计答案
} printf("%d", _ans);
return 0;
}

复杂度为O(nm logm)

100pts

以上做法的复杂度太高,这时候想有没有什么办法可以一遍就统计出所有分配方案的答案,然后统计答案。

统计答案的代码:

for (int i = 0; i <= n; i++) {
if (ans1[i] + ans2[n - i] > maxn) {
maxn = ans1[i] + ans2[n - i];
}
}

如果给每个廊桥都编上号,每次飞机入站都选择空闲的廊桥中编号最小的哪一个。

这样可以排除分配方案的影响。

用一个优先队列来维护廊桥编号,一开始将所有廊桥入队。

对于每一架飞机可以用一个pair分别存储飞机出站的时间以及停靠的廊桥的编号。

用优先队列来维护pair

每次飞机入站时先比较有没有应该出站的飞机,如果有就把他们从队列中弹出,并把对应的廊桥编号再加入优先队列中。

然后飞机选择编号最小的廊桥停靠。并把对应的廊桥的ans加一。

这样就能快速的统计出每个廊桥产生的贡献,再把所有编号比它小的廊桥产生的贡献加起来,用前缀和数组来维护。

最后用上面的代码统计一遍答案就好了。

代码如下:

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;
}

复杂度 O(nlogn)

Code

#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;
}

[CSP-S 2021] 廊桥分配 题解的更多相关文章

  1. [CSP-S2021] 廊桥分配

    链接: P7913 题意: 有 \(m_1\) 架飞机和 \(m_2\) 架飞机停在两个机场,每架飞机有到达和离开的时间,要将 \(n\) 个廊桥分给两个机场,每个廊桥同一时刻只能停一架飞机,需要最大 ...

  2. POJ 3694 Network(并查集缩点 + 朴素的LCA + 无向图求桥)题解

    题意:给你一个无向图,有q次操作,每次连接两个点,问你每次操作后有几个桥 思路:我们先用tarjan求出所有的桥,同时我们可以用并查集缩点,fa表示缩点后的编号,还要记录每个节点父节点pre.我们知道 ...

  3. UVA796 Critical Links(求桥) 题解

    题意:求桥 思路:求桥的条件是:(u,v)是父子边时 low[v]>dfn[u] 所以我们要解决的问题是怎么判断u,v是父子边(也叫树枝边).我们在进行dfs的时候,要加入一个fa表示当前进行搜 ...

  4. 上午小测3 T1 括号序列 && luogu P5658 [CSP/S 2019 D1T2] 括号树 题解

    前 言: 一直很想写这道括号树..毕竟是在去年折磨了我4个小时的题.... 上午小测3 T1 括号序列 前言: 原来这题是个dp啊...这几天出了好几道dp,我都没看出来,我竟然折磨菜. 考试的时候先 ...

  5. [CSP模拟测试43、44]题解

    状态极差的两场.感觉现在自己的思维方式很是有问题. (但愿今天考试开始的一刻我不会看到H I J) A 考场上打了最短路+贪心,水了60. 然而正解其实比那30分贪心好想多了. 进行n次乘法后的结果一 ...

  6. UOJ 2021 NOI Day2 部分题解

    获奖名单 题目传送门 Solution 不难看出,若我们单个 \(x\) 连 \((0,x),(x,0)\),两个连 \((x,y),(y,x)\) ,除去中间过对称轴的一个两个组,就是找很多个欧拉回 ...

  7. USACO 2021 Contest 1 Bronze 题解

    蒟蒻第一次打 USACO,只打了 Bronze 就跑路了.不得不说也有很有意思的题目.接下来就看看题目吧. 由于现在还看不到题目,只给出加工后的题目大意. T1 Lonely Photo Conten ...

  8. csp-s 2021

    T1 廊桥分配 当一架飞机抵达机场时,可以停靠在航站楼旁的廊桥,也可以停靠在位于机场边缘的远机位. 乘客一般更期待停靠在廊桥,因为这样省去了坐摆渡车前往航站楼的周折. 然而,因为廊桥的数量有限,所以这 ...

  9. CSP-J/S 2021 游记

    \(\large\texttt{Day -1}\) 晚上好累啊,去集训了,回来之后发现十一点了还码了一会儿,只能祈求上帝明天不会打瞌睡. \(\large\texttt{Day 0}\) 意料中的事情 ...

随机推荐

  1. 在linux查询本机的公网IP

    linux服务器查看公网IP信息的方法 最近在解决网络问题时,需要查看本机的出口公网IP信息,所以在网络上搜索和请求运维达人,获得如下两个方法: curl ifconfig.me 在linux系统中输 ...

  2. 论文解读(SimCLR)《A Simple Framework for Contrastive Learning of Visual Representations》

    1 题目 <A Simple Framework for Contrastive Learning of Visual Representations> 作者: Ting Chen, Si ...

  3. JDBC-1(概述&建立)

    基于宋红康老师所讲JDBC所作笔记 1.JDBC概述 1.1 数据持久化 持久化:将数据保持到可掉电式存储设备中以供之后使用. 数据持久化意味着将内存中的数据保存到硬盘上加以固化,实现过程大多通过各种 ...

  4. Docker系列(6)- 常用命令(2) | 镜像命令

    准备工作 知道查看官方文档,官方文档描述的很详细,并且每一种类型.每一个命令的选项都有例子 会使用docker --help查看 镜像命令 docker images 查看所有本地主机上的镜像 [ro ...

  5. MySQL 基础入门笔记

    目前我们已知的保存数据的容器有: 内存:( 数组,集合) 硬盘:(文件) 将数据从硬盘读取到内存始终是一个性能上的瓶颈 DB :      数据库  ( 保存一系列有组织的数据容器) DBMS:  数 ...

  6. 动图图解GC算法 - 让垃圾回收动起来!

    原创:码农参上(微信公众号ID:CODER_SANJYOU),欢迎分享,转载请保留出处. 提到Java中的垃圾回收,我相信很多小伙伴和我一样,第一反应就是面试必问了,你要是没背过点GC算法.收集器什么 ...

  7. 一篇文章搞定Selenium元素定位/封装/数据驱动

    小伙伴都知道,自动化最重的,又最"难"(因为实战中会碰到定位的各种坑)那就是定位元素.如果不熟练掌握定位,那只怕你比功能测式的小伙伴下班还会要晚!扎心了吧! Selenium常用定 ...

  8. 实时渲染基础(4)纹理(Texture)

    目录 纹理映射(Texture Mapping) 球形贴图(Spherical Map) 立方体贴图(Cube Map) 纹理走样问题 Mipmap 各向异性过滤(Ripmap) 纹理应用技术(Tex ...

  9. (目录)Fortran学习笔记:开坑!!!

    前言:因为某些原因,需要使用Fortran编写程序,记录下Fortran语法学习过程中的部分笔记.在此开坑记录,立下Flag,"希望年末能够更新完" Fortran 学习笔记 陈橙 ...

  10. 设置 SSH 命令行空闲保持会话

    楔子 使用 Mac 或 Linux 原生的命令行 ssh user@ip 方式连接 Linux 闲时会自动断开终端卡死. 为解决这个问题,查了到篇博客翻译下关键步骤记录下来.解决方式可以分服务端设置和 ...