专栏文章

题解:P14319 「ALFR Round 11」C1 开关灯 (switch) (ez ver.)

P14319题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@minhkjis
此快照首次捕获于
2025/12/02 02:32
3 个月前
此快照最后确认于
2025/12/02 02:32
3 个月前
查看原文

题意

nn 个灯泡,这 nn 个灯泡中含有一个损坏的灯泡,这些灯泡初始时都是暗的,你可以进行反转 lrl \sim r,查询 lrl \sim r 之间亮的灯泡的数量两个操作。

思路

注意到损坏的灯泡每次有概率反转,但反转不会连续进行两次,因此可以分为两种情况讨论。
  • 第一次操作损坏的灯泡没有反转,此时 1n1 \sim n 范围内有 n1n - 1 个灯泡是亮的。
  • 第一次操作损坏的灯泡反转了,此时 1n1 \sim n 范围内有 nn 个灯泡是亮的。
对于第一种情况,我们对其进行二分,对于每个 lmidl \sim mid 若这个区间没有损坏的灯泡,则其应当有 midl+1mid-l+1 个亮的灯泡,将 ll 设为 mid+1mid+1
对于第二种情况,先将其进行反转,此时由于损坏灯泡不能连续两次反转,1n1 \sim n 范围内应当有 11 个亮的灯泡,此灯泡为损坏的灯泡,二分求出损坏灯泡的位置。
最多操作次数为 log(n)+3\log(n)+3 次,不超过限制。

代码

CPP
#include<bits/stdc++.h>
using namespace std;
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int n;
		cin>>n;
		cout<<"1 1 "<<n<<endl;
		cout<<"2 1 "<<n<<endl;
		int now;
		cin>>now;
		if(now!=n) //损坏灯泡未反转
		{
			int l=1,r=n,ans=0;
			while(l<=r)//二分查询损坏灯泡
			{
				int mid=l+((r-l)>>1);
				cout<<"2 "<<l<<' '<<mid<<endl;
				int a;
				cin>>a;
				if(a!=mid-l+1)
				{
					ans=mid;
					r=mid-1;
				}
				else
				{
					l=mid+1;
				}
			}
			cout<<"3 "<<ans<<endl;
		}
		else //损坏灯泡在第一次操作反转
		{
			cout<<"1 1 "<<n<<endl;//再次反转,此时只有一个亮的灯泡即为损坏灯泡
			int l=1,r=n,ans=0;
			while(l<=r)
			{
				int mid=l+((r-l)>>1);
				cout<<"2 "<<l<<' '<<mid<<endl;
				int a;
				cin>>a;
				if(a!=0)
				{
					ans=mid;
					r=mid-1;
				}
				else
				{
					l=mid+1;
				}
			}
			cout<<"3 "<<ans<<endl;
		}
	}
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...