首页 > 其他分享 >CSP-S 2021 廊桥分配 题解

CSP-S 2021 廊桥分配 题解

时间:2023-09-29 20:56:01浏览次数:29  
标签:pq int 题解 top pop 停靠在 廊桥 CSP

part 1:

题目描述:

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

机场分为国内区和国际区,国内航班飞机只能停靠在国内区,国际航班飞机只能停靠在国际区。一部分廊桥属于国内区,其余的廊桥属于国际区。

L 市新建了一座机场,一共有 \(n\) 个廊桥。该机场决定,廊桥的使用遵循“先到先得”的原则,即每架飞机抵达后,如果相应的区(国内/国际)还有空闲的廊桥,就停靠在廊桥,否则停靠在远机位(假设远机位的数量充足)。该机场只有一条跑道,因此不存在两架飞机同时抵达的情况。

现给定未来一段时间飞机的抵达、离开时刻,请你负责将 \(n\) 个廊桥分配给国内区和国际区,使停靠廊桥的飞机数量最多。

输入格式

输入的第一行,包含三个正整数 \(n, m_1, m_2\),分别表示廊桥的个数、国内航班飞机的数量、国际航班飞机的数量。

接下来 \(m_1\) 行,是国内航班的信息,第 \(i\) 行包含两个正整数 \(a_{1, i}, b_{1, i}\),分别表示一架国内航班飞机的抵达、离开时刻。

接下来 \(m_2\) 行,是国际航班的信息,第 \(i\) 行包含两个正整数 \(a_{2, i}, b_{2, i}\),分别表示一架国际航班飞机的抵达、离开时刻。

每行的多个整数由空格分隔。

输出格式

输出一个正整数,表示能够停靠廊桥的飞机数量的最大值。

样例输入 #1

3 5 4
1 5
3 8
6 10
9 14
13 18
2 11
4 15
7 17
12 16

样例输出 #1

7

样例输入 #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

part 2

解析:

首先得以想到的是枚举所有可能,选择最优方案,这样的话时间复杂度约为 \(O(n^2)\) 在 \(n<=10^5\) 的情况下会超时。那么要怎么优化呢?
不妨这样想,一共有 \(n\) 个廊桥,如果给国内长区分 \(i (i<=n)\) 个,那么国际区就可以分到 \(n-i\) 个。那么就可以定义 \(f_i , g_i\) 分别为当分 \(i\) 个廊桥时能分到的廊桥个数。那么题目就转为求 \(f_i+g_{n-i}\) 的最大值。所以解题思路为:当有飞机抵达机场时如果还有空余的廊桥,则选择编号最小的一个停放,并使其廊桥贡献值加一。由于每当抵达机场时都要对廊桥编号进行排序,会占用大量时间,所以可以用堆来存放,最后用前缀和计算前 \(1-n\) 项和即可。

参考代码

#include<bits/stdc++.h>
#define bool char                                                                                                                                                                                                                                                                                                                                                                                                                                            //防盗水印       
using namespace std;
const int N = 1e6+5;
int n,m1,m2,f[N]={0},g[N]={0};
struct edge
{
	int be,en;
}a[N],b[N];
struct node
{
	int num,leave_t;
	node(){}
	node(int numm,int lea){num=numm;leave_t=lea;}
	bool operator < (const node& r) const
	{
		return leave_t>r.leave_t;
	}
};
bool cmp(edge x,edge y){return x.be<y.be;}
int main() 
{
	scanf("%d%d%d",&n,&m1,&m2);
	for(int i = 1;i<=m1;i++)
	scanf("%d%d",&a[i].be,&a[i].en);
	for(int i = 1;i<=m2;i++)
	scanf("%d%d",&b[i].be,&b[i].en);
	sort(a+1,a+1+m1,cmp);
	sort(b+1,b+1+m2,cmp);
	priority_queue<int, vector<int> ,greater<int> > p;  //存放空余的廊桥 
	priority_queue<node> pq;  //存放停在廊桥飞机的廊桥编号和离开时间 
	for(int i = 1;i<=n;i++) p.push(i); //初始所有廊桥均为空闲状态 
	for(int i = 1;i<=m1;i++)
	{
		while(!pq.empty()&&a[i].be>pq.top().leave_t){
			p.push(pq.top().num);
			pq.pop();
		}
		if(!p.empty())
		{
			pq.push(node(p.top(),a[i].en));
		    f[p.top()]++;
		    p.pop();
		}
		
	} 
	while(!p.empty()) p.pop();  //清空队列,优先队列不支持 clear() 
	while(!pq.empty()) pq.pop();
	for(int i = 1;i<=n;i++) p.push(i);
	for(int i = 1;i<=m2;i++)
	{
		while(!pq.empty()&&b[i].be>pq.top().leave_t){
			p.push(pq.top().num);
			pq.pop();
		}
		if(!p.empty())
		{
			pq.push(node(p.top(),b[i].en));
	    	g[p.top()]++;
	    	p.pop();
		}
	}
	for(int i = 2;i<=n/*千万别写成m1*/;i++) f[i]=f[i]+f[i-1];
	for(int i = 2;i<=n/*千万别写成m2*/;i++) g[i]=g[i]+g[i-1];  
	int ans=0;
	for(int i = 0;i<=n;i++)
	ans=max(ans,f[i]+g[n-i]);
	printf("%d",ans);
	return 0; 
}

标签:pq,int,题解,top,pop,停靠在,廊桥,CSP
From: https://www.cnblogs.com/demc/p/17737264.html

相关文章

  • [CF762D] Maximum path 题解
    [CF762D]Maximumpath题解想法首先考虑问题的弱化版,如果不能往左走,能取到的最大值是多少。这个问题可以用一个显然的DP解决,\(f_{i,j}\)表示走到第\(i\)列,第\(j\)行,并且不会再访问这一列其它的方格,能取到的最大值。转移可以从三个方向考虑,以\(f_{i,1}\)为例,黑色是当......
  • P2216 [HAOI2007] 理想的正方形 题解
    Description给定\(n\timesm\)的矩阵,找大小为\(k\timesk\)的子矩阵\(a\),使得子矩阵\(\max\{a\}-\min\{a\}\)最小。SolutionSolution1枚举所有\(k\timesk\)的子矩阵,然后枚举最大值和最小值,时间复杂度\(O(n^4)\),期望得分\(20\)分。Solution2求最大值和最小......
  • CF1425F Flamingoes of Mystery 题解
    题目传送门前置知识前缀和&差分解法令\(sum_k=\sum\limits_{i=1}^{k}a_k\)。考虑分别输入\(sum_2\simsum_n\),故可以由于差分知识得到\(a_i=sum_i-sum_{i-1}(3\lei\len)\),接着输入\(a_2+a_3\)的值从而求出\(a_2=sum_3-a_3,a_1=sum_2-a_2\)。同时因为是交互题,记......
  • 【题解】[CQOI2008] 传感器网络
    题意给定一张有向无环图,从中选出一棵有根树(节点编号为\(0\simn\),树根为\(n\)),使得除根节点外所有节点的出度的最大值最小。除根节点外,依次输出每个节点的父亲,并要求字典序最小。(\(1\len\le50\))*注意:由于个人习惯,这里将节点编号重编为\(1\simn+1\),根节点即为\(n+1\)......
  • 雅思 outweigh 议论题解答方法
    Doyouthinktheadvantagesoutweighthedisadvantages?1.这是两面写作题2.必须分出多少/高低3.所以说这个题目基本等同于discuss的弱强写作结构,不要给自己增加负担觉得新学了一种题目。结构安排:1.引出争论/背景句+给出明确的偏向(…..doesmoregoodthan harm.)2.先......
  • 2023 CSP-S 备战
    2023CSP-S备战日常犯智9.29Dinic中,如果rest为\(0\),直接终止循环。intdinic(intu,intflow){ if(u==T)returnflow; intrest=flow; for(inti=now[u];i&&rest;i=edge[i].nxt){//rest now[u]=i; intv=edge[i].v,c=edge[i].c; ......
  • 洛谷 P7075[CSP-S2020] 儒略日
    [CSP-S2020]儒略日题目描述为了简便计算,天文学家们使用儒略日(Julianday)来表达时间。所谓儒略日,其定义为从公元前4713年1月1日正午12点到此后某一时刻间所经过的天数,不满一天者用小数表达。若利用这一天文学历法,则每一个时刻都将被均匀的映射到数轴上,从而得以很方便的......
  • 济南 CSP-S NOIP 储备营笔记
    Day1上午——基础算法模拟+枚举小前言碰到题目不会做->先写个模拟压压惊()枚举法枚举的思想是不断地猜测,从所有可能的集合中一一尝试,然后再判断是否符合题目的条件。单独提到枚举时我们往往认为这是一个暴力做法,但事实上并非如此,恰当的枚举往往会是解题的关键步骤。......
  • Broken robot 题解
    题目链接Rrokenrobot分析记\(f[i][j]\)为从\(i\)行\(j\)列到最后一行的期望,则\(f[i][j]=\begin{cases}\frac{1}{3}(f[i][j]+f[i][j+1]+f[i+1][j])+1&i=1\\\frac{1}{4}(f[i][j]+f[i][j-1]+f[i,j+1]+f[i+1][j])+1&1<i<m\\\frac{1}{3}(f[i][j]......
  • git clone项目报错fatal: fetch-pack: invalid index-pack output问题解决
    gitclone项目报错fatal:fetch-pack:invalidindex-packoutput问题解决原因出现该问题的原因是gitclone的项目过大导致项目拉去失败解决方法首先拉去项目最后一次提交gitclone--depth=1项目地址;拉取全部项目内容gitfetch--unshallow,一般不大的项目都可以......