P13750 [NWERC 2024] Limited Library

传送门

题目描述

在暑假期间,校园里居住的学生较少,因此这是为代尔夫特理工大学图书馆增添新书的绝佳时机。这些新书的宽度都相同,但高度各不相同。由于现有的书架都已满,图书馆管理委员会决定新增一个书架来展示这些新书。

新书架有若干层,每层高度不同。每层最多可放 x x x 本书。由于可能会有剩余空间,管理委员会还希望在书架上展示一些艺术品,每层最多放一个艺术品。只有当该层旁边最多有 y y y 本书时,艺术品才能放下,因为艺术品占据与 x − y x-y x−y 本书相同的空间。例如,图 L.1 展示了一个书架,其中有三层可以放置艺术品。

管理委员会希望你找出,在能够放下所有新书的前提下,最多能在多少层上放置艺术品。

输入格式

输入包括:

  • 一行四个整数 n n n、 m m m、 x x x、 y y y( 1 ≤ n , m ≤ 10 5 1 \leq n, m \leq 10^5 1≤n,m≤105, 1 ≤ y < x ≤ 1000 1 \leq y < x \leq 1000 1≤y<x≤1000),分别表示书架的层数、新书的数量、每层最多可放的书本数、每层与艺术品并排时最多可放的书本数。
  • 一行 n n n 个整数 a a a( 1 ≤ a ≤ 10 9 1 \leq a \leq 10^9 1≤a≤109),表示每层的高度。
  • 一行 m m m 个整数 b b b( 1 ≤ b ≤ 10 9 1 \leq b \leq 10^9 1≤b≤109),表示每本书的高度。

输出格式

如果能将 m m m 本书全部放入 n n n 层书架中,输出最多能放置的艺术品数量。否则,输出" impossible \texttt{impossible} impossible"。

输入输出样例 #1

输入 #1

复制代码
4 8 4 2
4 8 6 2
1 2 3 5 7 7 8 8

输出 #1

复制代码
3

输入输出样例 #2

输入 #2

复制代码
4 11 3 2
2 2 2 2
1 1 1 1 1 1 1 1 1 1 1

输出 #2

复制代码
1

输入输出样例 #3

输入 #3

复制代码
2 10 3 2
8 6
4 2 1 3 6 2 1 3 4 5

输出 #3

复制代码
impossible

输入输出样例 #4

输入 #4

复制代码
3 8 8 3
7 9 4
2 3 4 5 6 7 8 9

输出 #4

复制代码
3

题意

现在有 n n n 层书架,每层最多可放 x x x 本书,又有 m m m 本新书要放进书架里,且在放书时放的书的高度不得超过该层书架高度。

同时我们希望能放更多艺术品,每层最多放 1 1 1 个艺术品,且只有当该层旁边最多有 y y y 本书时,艺术品才能放下。

求在能够放下所有新书的前提下,最多能放多少艺术品,若新书都无法放完,则输出 impossible

思路

因为求的是放的艺术品数,所以可以用二分来求艺术品数(因为若放 k k k 个艺术品可行,那么放更少的留的空间还会更大,一样可行,满足二分单调性)。

而且因为每层能放的书的数量是一样的,矮书既能放高层又能放矮层,但高书只能放高层,所以最优策略为矮书放矮层,高书放高层。

同理,艺术品放矮层比放高层也要更优。

所以先对每本书和每层书架的高度都升序排序。

接着二分答案,check 中在前 m i d mid mid 层放 y y y 本书,其他层放 x x x 本书,最后看是否放完所有书即可。

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m,x,y,l,r,ans=-1;//先为答案赋值为 -1,若最后还是 -1 则表示一直都没合法过,输出 impossible
vector<int> a,b;
bool check(int k)
{
	int j=0;
	for(int i=0;i<k&&j<m;i++)//在前 mid 层放 y 本书 
	{
		int cnt=y;
		while(cnt--&&j<m&&b[j]<=a[i])
			j++;
	}
	for(int i=k;i<n&&j<m;i++)//在其他层放 x 本书
	{
		int cnt=x;
		while(cnt--&&j<m&&b[j]<=a[i])
			j++;
	}
	return j>=m;//判断书是否放完
}
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>n>>m>>x>>y;
	r=n;
	a.resize(n);
	b.resize(m);
	for(int i=0;i<n;i++)
		cin>>a[i];
	for(int i=0;i<m;i++)
		cin>>b[i];
	sort(a.begin(),a.end());
	sort(b.begin(),b.end());//排序
	while(l<=r)//二分答案
	{
		int mid=(l+r)>>1;
		if(check(mid))
			ans=mid,l=mid+1;
		else 
			r=mid-1;
	}
	if(ans==-1)//一直都放不完
		cout<<"impossible";
	else
		cout<<ans;
	return 0;
}
相关推荐
承渊政道10 分钟前
【贪心算法】(经典实战应用解析(四):分发饼干、最优除法、跳跃游戏、跳跃游戏Ⅱ、加油站)
数据结构·c++·算法·leetcode·贪心算法·动态规划·哈希算法
承渊政道1 天前
【贪心算法】(经典实战应用解析(三):K次取反后最⼤化的数组和、按⾝⾼排序、优势洗牌、最⻓回⽂串、增减字符串匹配)
数据结构·c++·学习·算法·贪心算法·线性回归·哈希算法
阿部多瑞 ABU1 天前
运动会智能编排系统 - 完整详细需求规格说明书
python·贪心算法·vue·html
hnjzsyjyj1 天前
洛谷 B4359:[GESP202506 三级] 分糖果 ← 贪心算法
贪心算法
YuanDaima20482 天前
贪心算法基础原理与题目说明
数据结构·人工智能·python·算法·贪心算法·手撕代码
不太会a3 天前
Educational Codeforces Round 175 (Rated for Div. 2) C
贪心·二分
m0_737539374 天前
pod Scheduler调度
算法·贪心算法
小夏子_riotous4 天前
Kubernetes学习路径——5. Kubernetes 实战入门:Namespace、Pod、Label、Deployment 与 Service 全解析
学习·贪心算法·kubernetes
zB6822HbX6 天前
狙击模拟《Center Mass: Streets of Ramadi》Steam页面 发售日待定
贪心算法·排序算法·动态规划
承渊政道6 天前
【贪心算法】(经典实战应用解析(二):最⻓递增⼦序列、递增的三元⼦序列、最⻓连续递增序列、买卖股票的最佳时机、买卖股票的最佳时机II)
数据结构·c++·学习·算法·leetcode·贪心算法·哈希算法