CF1867C Salyg1n and the MEX Game

去洛谷看我的博客

思路

看着无从下手,实际上又是一道诈骗题。

假设原数列不存在 0 0 0,那么我们可以直接加入 0 0 0,然后游戏结束,假设答案是 k k k。那么,如果我们选择加入 k k k,来试图让答案变大,那么 Bob 就会移除一个数,最优的话是 1 1 1,这样的话,你无论加入 1 1 1 还是 0 0 0,答案都不会超过 1 1 1,于是一手好牌就被你打没了,就算 Bob 不移除 1 1 1,移除 x x x,你的最终答案也不会超过 x x x 了。

(因为 Bob 只能移除比你加入的数还要小的数,所以如果你操作不好,Bob 甚至还没法让你)

那么,我们直接猜测最优的操作是每次加入目前集合中不存在的最小的数。

蒟蒻大概证明一下:

假设目前最小的不存在的数是 x x x,那么 [ 0 , x ) [0,x) [0,x) 都应该是存在的,那么加入以后 [ 0 , x ] [0,x] [0,x] 都是存在的,答案为 x + 1 x+1 x+1,此时 Bob 会移除中间的某个数,那么我们再加回来,直到 Bob 移除了 0 0 0,然后你添加了 0 0 0,游戏结束。

但是如果你不加入 x x x,那么,Bob 再随便移除一个数 y y y,这时,如果你使用之前的策略,答案也只是 x x x,不使用的话,Bob 再移除一个小于 y y y 的数,答案将会再次变小,你就会无力回天了。

所以想要答案尽可能的大,我们就只能每次选择最小的不存在的数。

蒟蒻在开始想的是拿个 set 存,但是,显然 set 的常数是接受不了的,可以想象,如果数据是 [ 0 , n − 1 ] [0,n-1] [0,n1],那么 Bob 就可以和你扯大约 n n n 次皮,加上 set log ⁡ n \log n logn 的复杂度,轻松让你 TLE

当然,也可能是我操作 set 有问题,因为我是把前 1 0 5 10^5 105 都统计进了一个 set,然后再转一遍到另一个 set,并且赛后才发现给的是有序的,连最开始的 set 也不需要。(果然 OI 学多了,会掉视力)

然后蒟蒻转念一想,如果最开始加入 x x x,那么 Bob 无论取走那个数,下一次最小的都一定是 Bob 取走的那个数。

原来这么简单,赛时交了一发 TLE 一定是我脑抽了。

AC code

#include<bits/stdc++.h>
using namespace std;
int T,n,a,p;
set<int>s;
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		cin>>n,s.clear();
		for(int i=1;i<=n;++i) cin>>a,s.insert(a);
		for(int i=0;i<=100000;++i) if(!s.count(i)){p=i;break;}//这里只是为了方便找到第一次的答案,所以用了set
     //其实不需要的,因为给的本身就是有序的,但是赛时没看到,现在又懒得改了。。。
		while(1)
		{
			cout<<p<<endl;//上文是指这里用了set
			cin>>a;
			if(a==-1||a==-2) break;
			p=a;
		}
	}
	return 0;
}
 
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值