WEEK5训练赛

本文介绍了如何在保留部分座位的同时,最大化教室座位相邻两排的最小间距,以符合疫情防控需求。通过空出指定排座位,目标是使剩余座位间的最小间距最大化。问题转化为求解最优化问题,可能涉及二分查找等算法策略。
摘要由CSDN通过智能技术生成

教室里有 nn 排座位。处于疫情防控的目的,希望你空出 mm 排座位, mm 排位置空出后,剩下的座位的相邻两排间隔就会增加,这样就可以减少聚集了。
现在需要你最大化剩余的相邻两个座位间距的最小值,并输出最大化后的结果。

输入格式

第一行两个整数 n,m(1 \leq n \leq 2\times 10 ^5,0 \leq m \leq n)n,m(1≤n≤2×105,0≤m≤n),表示共有 nn 排座位,需要空出 mm 排。
第二行 n - 1n−1整数,第 ii 个整数 d_i(1\leq d_i \leq 10^4)di​(1≤di​≤104) 表示第 ii 排座位和第 i + 1i+1 排座位间隔距离为 d_idi​。

输出格式

一个整数, 表示最大化后的结果。

输入输出样例

输入 #1复制

5 1
2 1 1 2

输出 #1复制

2

输入 #2复制

5 3
1 2 3 4

输出 #2复制

10

答案具有单调性,且最大值最小,优先考虑二分,由于两排间距离不好check,先将其转化为每排的位置坐标,然后通过距离进行check。

r一定要开的够大,比赛时候其实别的都写对了,就是r开小了一直卡在第十个点,补题时候也一直卡在这个点。/(ㄒoㄒ)/~~

 #include<bits/stdc++.h>
#define ll long long
using namespace std;

bool ck(ll x);

ll a[222222],s[222222],n,m,l=0,r=0x7fffffff,mid;

int main()
{
	cin>>n>>m;
	s[1]=0;
	memset(a,0,sizeof(a));
	memset(s,0,sizeof(s));
	for(int i=2;i<=n;i++)
	{
		cin>>a[i];
		s[i]=s[i-1]+a[i];
	}
	while(l<=r)
	{
		mid=l+r>>1;
		ck(mid)?l=mid+1:r=mid-1;
	}
	cout<<l-1;
	return 0;
}

bool ck(ll x)
{
	int p=0,tot=0;
	for(int i=2;i<=n;i++)
	{
		s[i]-s[p]<x?tot++:p=i;
	}
	return tot<=m;
}

Number Game

题目描述

Alice and Bob are playing a game. They have an array of positive integers aa of size nn .

Before starting the game, Alice chooses an integer k \ge 0k≥0 . The game lasts for kk stages, the stages are numbered from 11 to kk . During the ii -th stage, Alice must remove an element from the array that is less than or equal to k - i + 1k−i+1 . After that, if the array is not empty, Bob must add k - i + 1k−i+1 to an arbitrary element of the array. Note that both Alice's move and Bob's move are two parts of the same stage of the game. If Alice can't delete an element during some stage, she loses. If the kk -th stage ends and Alice hasn't lost yet, she wins.

Your task is to determine the maximum value of kk such that Alice can win if both players play optimally. Bob plays against Alice, so he tries to make her lose the game, if it's possible.

输入格式

The first line contains a single integer tt ( 1 \le t \le 1001≤t≤100 ) — the number of test cases.

The first line of each test case contains a single integer nn ( 1 \le n \le 1001≤n≤100 ) — the size of the array aa .

The second line contains nn integers a_1, a_2, \dots, a_na1​,a2​,…,an​ ( 1 \le a_i \le n1≤ai​≤n ).

输出格式

For each test case, print one integer — the maximum value of kk such that Alice can win if both players play optimally.

题意翻译

一共有 tt 组数据,每次有一个序列 aa ,两个人对它进行操作,一共进行 kk 个回合。在第 ii 个回合中,第一个人必须在序列 aa 不为空的情况下删除序列 aa 任意一个小于等于 k-i+1k−i+1 的数。接着,第二个人必须在序列 aa 不为空的情况下将 k-i+1k−i+1 加到序列 aa 中任意一个数上。当 kk 个回合结束时,如果第一个人每一回合都操作过了,第一个人就赢了,否则就输了。求保证让第一个人赢的情况下 kk 最大是多少。

输入输出样例

输入 #1复制

4
3
1 1 2
4
4 4 4 4
1
1
5
1 3 2 1 1

输出 #1复制

2
0
1
3

答案是线性的,所以先想到二分,check函数只需模拟二人操作即可,对于二人操作的策略,只需贪心的分别取最大和最小。

#include<bits/stdc++.h>
#define re register
#define ll long long
#define maxn 111
#define INF 0x7fffff
using namespace std;

bool ck(ll x);

ll a[maxn],b[maxn],l,r,mid,t,n;

int main()
{
	cin>>t;
	while(t--)
	{
		cin>>n;
		l=0;
		r=INF;
		memset(a,0,sizeof(a));
		for(int i=1;i<=n;i++)
		{
			cin>>a[i];
		}
		while(l<=r)
		{
			mid=l+r>>1;
			ck(mid)?l=mid+1:r=mid-1;
		}
		cout<<r<<endl;	
	}
	return 0;
}

bool ck(ll x)
{
	for(re int i=1;i<=n;i++)
	{
		b[i]=a[i];
	}
	for(re int k=x;k>=1;k--)
	{
		sort(b+1,b+1+n,greater<int>());
		int p=lower_bound(b+1,b+n+1,k,greater<int>())-b;
		if(p==n+1)
			return 0;
		b[p]=INF;
		b[n]+=k;
	}  
	return 1;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值