CF - C. Number Game(思维,博弈)

https://codeforces.com/contest/1749/problem/C

题意
给定一个长度为 n 的数组 a[]。
游戏开始之前,Alice 选择一个数字 k,表示进行 k 轮游戏。

每一轮 Alice 和 Bob 各对数组 a[] 操作一次:

  • 如果当前是第 i 轮的话,Alice 必须删掉一个小于等于 k-i+1 的数;
  • 然后,如果数组非空的话,Bob 选择一个数使其加上 k-i+1

如果到某一轮 Alice 无法操作(剩下元素都比 k-i+1 大 或者 数组为空),Alice 输。
如果 k 轮结束 Alice 都没有输的话,Alice 就赢。

Bob 尽量不让 Alice 赢。如果两者都采取最佳操作,问 Alice 能赢的最大 k 为多少?

1 ≤ t ≤ 100 ,   1 ≤ n ≤ 100 ,   1 ≤ a i ≤ n 1≤t≤100,\ 1 \le n \le 100,\ 1 \le a_i \le n 1t100, 1n100, 1ain

思路
也就是说,第 1 轮 Alice 删掉 ≤ k 的一个数,Bob 让一个数加上 k;第二轮 Alice 删掉 ≤ k-1 的一个数,Bob 让一个数加上 k-1;…

一开始想的是,假设当前 Alice 要删掉 ≤ k 的数,她肯定会删掉剩下的数中小于等于 k 的最大的数,把较小的数剩下留着下面的轮次再删(因为下面轮次要删的数会更小)。
然后就想,Bob 会阻止 Alice 执行 k 轮,那么 Bob 就要操作她下一轮能够删掉的数(小于等于 k-1 的最大的数),让她下一轮操作不了,那她就输。
其实 Bob 的这种想法并不是最优的。因为最后 Alice 如果要赢的话一定要操作满 k 轮,而最后一轮 Alice 一定要删掉一个小于等于 1 的数,如果 Bob 在前几轮能够直接阻击掉 Alice 所有最终要删掉的 1,那么 Alice 最后无论如何都不能赢。所以 Bob 的最佳操作应该是,在每一轮操作时,都操作搞掉一个 1。

那么,如果 k 大于数列中 1 的个数 cnt 的话,所有的 1 都会被 Bob 搞掉,Alice 最后一轮无法操作,必输。
所以就只需要枚举 1~cnt,看 Alice 是否每一轮都能操作。

其实发现,如果 k 比较大的时候 Alice 能赢的话,k 比较小的时候一定也能赢,具有二段性,可以二分。
时间复杂度可以优化到O(Tnlognlogn)。(甚至有O(Tnlogn)和O(Tn) 的做法

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

#define Ios ios::sync_with_stdio(false),cin.tie(0)

const int N = 200010, mod = 1e9+7;
int T, n, m;
int a[N];

bool check(int k)
{
	multiset<int> st;
	for(int i=1;i<=n;i++) st.insert(a[i]);
	
	for(int i=k;i>=1;i--)
	{
		auto it = st.upper_bound(i);
		if(it == st.begin()) return 0;
		it --;
		st.erase(it);
		
		if(st.size())
		{
			it = st.begin();
			int x = *it;
			st.erase(it);
			st.insert(x + i);
		}
	}
	return 1;
}

signed main(){
	Ios;
	cin >> T;
	while(T--)
	{
		cin >> n;
		int cnt = 0;
		for(int i=1;i<=n;i++){
			cin >> a[i];
			if(a[i] == 1) cnt ++;
		}
		
		int l = 0, r = cnt;
		while(l < r)
		{
			int mid = l + r + 1 >> 1;
			if(check(mid)) l = mid;
			else r = mid - 1;
		}
		cout << l << endl;
//		int maxa = 0;
//		for(int k=1;k<=cnt;k++) if(check(k)) maxa = max(maxa, k);
//		cout << maxa << endl;
	}
	
	return 0;
}
  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
当您尝试重新启动 isc-dhcp-server 服务,如果出现“Job for isc-dhcp-server.service failed because the control process exited with error code”的错误消息,则表示 isc-dhcp-server 服务无法正常启动。要解决此问题,您可以执行以下步骤: 1. 检查 /etc/dhcp/dhcpd.conf 文件是否存在,并确保其格式正确。您可以使用以下命令检查配置文件: ``` sudo dhcpd -t -cf /etc/dhcp/dhcpd.conf ``` 如果此命令返回任何错误,请修改配置文件并重新运行命令,直到不再出现错误。 2. 检查 /etc/default/isc-dhcp-server 文件中的变量是否正确设置。确保 DHCPDv4_CONF 和 DHCPDv6_CONF 变量中的接口名称正确,并且没有任何语法错误。 3. 确保您的服务器上没有其他 DHCP 服务器正在运行。如果您的服务器上已经运行了其他 DHCP 服务器,则 isc-dhcp-server 服务将无法启动。您可以使用以下命令停止其他 DHCP 服务器: ``` sudo systemctl stop dnsmasq.service ``` 然后再尝试启动 isc-dhcp-server 服务。 4. 检查系统日志以获取有关服务启动失败的更多详细信息。您可以使用以下命令查看服务的状态和日志: ``` sudo systemctl status isc-dhcp-server.service sudo journalctl -xeu isc-dhcp-server.service ``` 这将显示与 isc-dhcp-server 服务相关的所有系统日志条目,以帮助您进一步诊断问题。 通过执行上述步骤中的一个或多个,您应该能够解决 isc-dhcp-server 服务启动失败的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值