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;
}
相关推荐
稷下元歌1 天前
七天学会plc加机器视觉之AI 接入 外设模块开发全详细操作文档(全程配套视频按文档实操)
python·sql·qt·贪心算法·r语言·wpf·时序数据库
Fms_Sa2 天前
贪心算法-背包问题
算法·贪心算法·c#
Cthy_hy3 天前
拓扑排序超详解:原理 + Kahn 贪心算法
python·算法·贪心算法
wabs6663 天前
关于贪心算法【968.监控二叉树】的想法
算法·贪心算法
wabs6664 天前
关于贪心算法的思考
算法·贪心算法
哈泽尔都5 天前
运动控制教学——5分钟学会力控算法(阻抗/导纳/力位混合)
c++·python·算法·决策树·贪心算法·机器人·gpu算力
碎碎念_4925 天前
”二分“高频题型总结:最小最大值、最大最小值、满足条件最小 / 最大
算法·二分
wabs6666 天前
关于贪心算法【划分字母区间】的问题总结(C++语法)
算法·贪心算法
迈巴赫车主6 天前
贪心算法
算法·贪心算法
重生之我是Java开发战士6 天前
【贪心算法】整数替换,俄罗斯套娃信封问题,可被三整除的最大和,距离相等的条形码,重构字符串
算法·贪心算法