CSP-S 2021 廊桥分配

news/2024/10/4 15:30:00

2021年的提高组第一题

学校模拟测试的时候居然想到了AC的代码(((bushi

luogu P7913

题目意思

  大体意思就是有n个廊桥,m1起国内航班,m2起国际航班,国内区和国际区是分开的,把n个廊桥分到两个区,飞机想要尽可能的停在廊桥处,而不停在远机处,每架飞机都有各自的起降时间,廊桥按到达顺序供给飞机,问怎么分廊桥可使得停在廊桥的飞机最多?

  数据范围:1n105,m1,m2≥1,m1+m2≤105,ai<bi≤108

思路

 因为题目中说廊桥是按飞机抵达的先后顺序分配的,我先想到了一个暴力思路:就是枚举分给国内的廊桥的个数(则分给国外的廊桥个数为n-i),再去枚举国内国外能有多少架飞机可以停在廊桥,取和的最大值,这个思路的复杂度在不优化的情况下大概是O(n^2(m1+m2)),这个复杂度一眼就知道会炸,大概只能过前20%的数据

  接着,我否定了我上一个暴力思路后又想出了更好的一个暴力思路(别问我为啥老想暴力思路,因为正解也不是那么容易能思考出来的,这个离着我的AC思路已经很近了):我们不如先假设廊桥有无数个,去遍历国内(国外)的航班,设一个sum[i]表示第i个廊桥会停几架飞机,如果此时有空机位,飞机就停在空机位,sum[i]++,否则廊桥数tot++,sum[tot]=1,最后再用一个前缀和p,就可以求出当有i个廊桥的时候,可以停放多少飞机。

  这个思路的时间复杂度是O(n*(m1+m2)),完全可以过掉前40%的点了。但是我的目标是正解,我们发现,在找空机位的时候特别浪费时间,是O(n)的复杂度,我们应该去考虑一种log级别的方法。

  我先考虑的就是优先队列q1(太香了),把廊桥的编号和飞机起飞时间压入队列,按起飞时间由小到大排序,如果队首元素起飞时间大于当前遍历到的飞机,那么直接新建廊桥,否则将其停在队首廊桥上,压入队列。

 注意!这里我犯了个非常致命的错误!!!

  如果只是判定是否需要新建廊桥,是没有问题的,但是如果直接停在队首廊桥就会出现一个错误——可能会有编号更小的廊桥可以停,这样就会导致:假设这个飞机是可以停在1号廊桥,但由于3号廊桥的飞机起飞更早,导致该飞机停在了3号廊桥(所以会有啥后果呢?),那么我们在存储sum[i]的时候,就会把该飞机编入3号廊桥,也就是说至少要给国内分配3个廊桥时该飞机才可以停,那这显然不行。

正解

  于是,我又增加了一个优先队列q2,用来从小到大存当前空机位廊桥的编号,如果有飞机的降落时间大于q1队首的起飞时间,那么我们直接把队首元素弹出,并把所对的廊桥编号压入q2,然后取q2队首编号的廊桥作为当前飞机的停机点。如果飞机的降落时间小于q1队首的起飞时间,先看看q2是否有空机位,如果没有再创建一个廊桥。时间复杂度是O((m1+m2)logn),可以过。

代码

  考试时写的代码,难看繁琐,勿喷

#include <bits/stdc++.h>
using namespace std;
int n,m1,m2;struct qu{int l;int r;
};
qu s1[101000],s2[101000];struct node{int id;int ti;bool operator < (const node &x) const{return ti>x.ti;}
};priority_queue<node> q;
priority_queue<int,vector<int>,greater<int> > q2; 
int sum1[101000],sum2[101000],p1[101000],p2[101000];
int tot1,tot2;bool cmp(qu x,qu y){return x.l<y.l;
}
int main (){cin >> n >> m1 >> m2;for(int i=1;i<=m1;i++)cin >> s1[i].l >> s1[i].r;for(int i=1;i<=m2;i++)cin >> s2[i].l >> s2[i].r;sort(s1+1,s1+m1+1,cmp);//先按降落时间从小到大排序 sort(s2+1,s2+m2+1,cmp);for(int i=1;i<=m1;i++){if(q.empty()||q.top().ti>s1[i].l){//如果当前所用着的廊桥已经没有可以停下的了 if(!q2.empty()) {//如果有空机位先停空机位 sum1[q2.top()]++;q.push({q2.top(),s1[i].r});q2.pop();continue;}sum1[++tot1]++;//否则新建廊桥 q.push({tot1,s1[i].r});}else{while(!q.empty()&&q.top().ti<=s1[i].l){//先把所有符合要求的廊桥出队 node u=q.top();q2.push(u.id);//压入q2 q.pop();}sum1[q2.top()]++;//sum存储 q.push({q2.top(),s1[i].r});q2.pop();}}while(!q.empty()) q.pop();//清空q1 q2 while(!q2.empty()) q2.pop();for(int i=1;i<=n;i++) p1[i]=p1[i-1]+sum1[i];//前缀和求p,表示i个廊桥可停几个飞机 for(int i=1;i<=m2;i++){//国外同理 if(q.empty()||q.top().ti>s2[i].l){if(!q2.empty()) {sum2[q2.top()]++;q.push({q2.top(),s2[i].r});q2.pop();continue;}sum2[++tot2]++;q.push({tot2,s2[i].r});}else{while(!q.empty()&&q.top().ti<=s2[i].l){node u=q.top();q2.push(u.id);q.pop();}sum2[q2.top()]++;q.push({q2.top(),s2[i].r});q2.pop();}}for(int i=1;i<=n;i++) p2[i]=p2[i-1]+sum2[i];int ans=0;for(int i=0;i<=n;i++){//枚举廊桥的分配个数 ans=max(ans,p1[i]+p2[n-i]); //取最大值 }cout << ans;return 0;
}

总结

  总体来说第一题还是有一定的思维的,这是本蒟蒻第一次写题解,若有什么问题请指出

下课!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/67669.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

SQL--约束,范式

约束 唯一约束 一个表可以多个字段加 值唯一性 非空约束 一个表可以多个字段加 值不能为空 主键约束 一个表只有一个字段可以加 值不能为空 值必须唯一性 自增约束 数据类型 数值类型 一般配合#键约束使用 默认约束 一个表可以多个字段加 没有给值的时候 使用…

【SpringBoot】结合Redis实现缓存

Redis经常用于缓存。接下来,我们以Springboot框架为例。实现一些Redis的基础操作,创建完SpingBoot项目后,具体步骤如下图: pom中添加项目依赖<!-- Redis 缓存--> <dependency><groupId>org.springframework.boot</groupId><artifactId>sprin…

探索JVM的垃圾回收(堆内存)

Java 8+ -序章 在 C/C++ 语言中,程序员自己分配内存、回收内存,不存在垃圾回收一说。 而在 Java 中,内存分配 绝大多数 是 JVM 的工作——栈内存、堆内存、永久代/元空间 等。ben发布于博客园 内存分配了就完了吗?不。JVM 运行时 的 内存不是无限的,受制于 程序员配置、系…

扩散引导语言建模(DGLM):一种可控且高效的AI对齐方法

随着大型语言模型(LLMs)的迅速普及,如何有效地引导它们生成安全、适合特定应用和目标受众的内容成为一个关键挑战。例如,我们可能希望语言模型在与幼儿园孩子互动时使用不同的语言,或在撰写喜剧小品、提供法律支持或总结新闻文章时采用不同的风格。 目前,最成功的LLM范式是训练…

day9[探索 InternLM 模型能力边界]

Bad Case 1:模型服务来源 https://opencompass.org.cn/arena您的输入 10月中旬去北京穿什么衣服模型A internlm2.5-20b-chat模型B Doubao-pro-32k/240828 (字节豆包)模型A输出|| 模型B输出 | || 其他补充 | xxxx | Bad Case 2:模型服务来源 https://opencompass.org.cn/aren…

(七)项目实战01-框架说明

全局通讯直接写入数据模型Model

卸载时报错:‘’系统找不到指定的驱动器‘’问题处理

操作系统:win11 问题描述:wegame,英雄联盟我早就卸载过了,今天在 设置/应用/安装的应用 这里又看见了,在此处点击卸载,报如下错误:解决办法: 查了一下网上的做法,大多数是删除注册表,我也试了几个,结果还是没有用。 最后灵机一动,记得控制面板那边也有卸载应用的位置…

[leetcode 25]. K 个一组翻转链表

题目描述: https://leetcode.cn/problems/reverse-nodes-in-k-group 给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。 k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。 你不能只是…