LGP14319 「ALFR Round 11」C1 开关灯 (switch) (ez ver.)
注意到题目的关键性质“损坏的灯泡不会连续两次取反”,所以可以通过至多两次操作能让这个灯泡“与众不同”。具体地,考虑在 \([1,n]\) 操作一次,此时调用一次查询 \([1,n]\) 可能会查出 \(n-1\) 盏或 \(n\) 盏亮的灯。如果是 \(n\) 个,那么就考虑再 \([1,n]\) 翻转一次,此时 \([1,n]\) 中只可能有一盏亮着的灯。
- 如果是第一次查出 \(n-1\),那么就直接开始二分查找灭的那一盏;
- 否则,就再集体翻转一次,然后查找亮的那一盏。
这样只需 \(2 \sim 3\) 次操作再加上 \(O(\log n)\) 次二分查找就可以查出来了,可以通过。
笑点解析:没看到多测 WA 了两发(
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
constexpr int N=-1;
int n,tmp;
void operate(int l,int r){cout<<"1 "<<l<<' '<<r<<endl;}
int ask(int l,int r){cout<<"2 "<<l<<' '<<r<<endl;cin>>tmp;return tmp;}
void answer(int x){cout<<"3 "<<x<<endl;}
void solve()
{
cin>>n;
operate(1,n);
int res=ask(1,n);
if(res==n-1) //这一次已经让坏灯暴露出来,二分查找
{
int l=1,r=n;
while(l<r)
{
int mid=(l+r)>>1;
if(ask(l,mid)==mid-l+1) l=mid+1;
else r=mid;
}
answer(l);
}
else //这一次还没暴露,再关一次
{
operate(1,n);
int l=1,r=n;
while(l<r)
{
int mid=(l+r)>>1;
if(ask(l,mid)==0) l=mid+1;
else r=mid;
// cerr<<l<<' '<<r<<'\n';
}
answer(l);
}
}
int main()
{
// freopen("neuvillette.in","r",stdin);
// freopen("neuvillette.out","w",stdout);
int T; cin>>T;
while(T--) solve();
return 0;
}

浙公网安备 33010602011771号