Codeforces Round #770 (Div. 2) D.Finding Zero题解

Finding Zero

思路:刚拿到题目就看到最多提问2n-2次,仔细一想:如果能找到最大值,那么就可以花n-2次来找到0,原理很简单,遍历1 maxid i,不断更新max() - min()的最大值,最后得到一个下标ansid,可以知道0一定是在1或者ansid之中,直接输出即可。所以只需要花n次提问来找最大值,后面一直处理不好,结果第二天才解出来。
解释一下代码:刚开始花n-2次提问去找最大值的下标(选2个数不动,循环n-2次),得出来的maxid可能是0,可能是最大值,也可能是一个很特殊的值(既不是最大值也不是最小值,但是却能让max()-min()最大),所以maxid不一定是最大值下标,于是最后需要另外判断一下,第二次花n-2次提问1 maxid i去找最小值的下标,得到ansid,所以最大值和最小值就在 1 maxid ansid 之中,再花2次提问来排除那个中间值。

(小白的思路,可能讲的不是很清楚,下面代码有注解)

AC代码如下:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    ios::sync_with_stdio(false);
    //cin.tie(0) , cout.tie(0);
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n; 
        int maxid = -1,x,maxx = -1;
        for(int i=3;i<=n;i++){
            cout<<"? "<<1<<" "<<2<<" "<<i<<endl;
            cin>>x;
            if(x > maxx){
                maxx = x;
                maxid = i;
            }
        }
        //maxid 要么是最大值 要么是0 要么是一个很特殊的值
        maxx = -1;
        int ansid = -1;
        for(int i=2;i<=n;i++){
            if(i != maxid){
                cout<<"? "<<1<<" "<<maxid<<" "<<i<<endl;
                cin>>x;
                if(x > maxx){
                    ansid = i;//如果maxid是0 那ansid就是最大值 maxid是最大值  ansid就是0
                    maxx = x;
                }
            }
        }
        //剩下 1 maxid ansid ,来判断一下哪个是中间值
		//取一个无关变量testid
        int testid = -1; //存一下用来测试的下标
        if(maxid!=2 && ansid != 2){
            cout<<"? "<<maxid<<" "<<ansid<<" "<<2<<endl;
            testid = 2;
        }
        else if(maxid!=3 && ansid!=3){
            cout<<"? "<<maxid<<" "<<ansid<<" "<<3<<endl;
            testid = 3;
        }
        else if(maxid!=4 && ansid!=4){
            cout<<"? "<<maxid<<" "<<ansid<<" "<<4<<endl;
            testid = 4;
        }
        cin>>x;
        if(x != maxx){ //如果maxid和ansid相减还不是最大值的话 说明下标1肯定是最大值最小值之一
            cout<<"? "<<1<<" "<<maxid<<" "<<testid<<endl;
            cin>>x;
            if(x != maxx){ //如果1 和 maxid的差值还不是最大值的话 说明0就在ansid 和 1中
                maxid = 1; //把maxid替换成1
            }
            else{
                ansid = 1; //否则把ansid替换成1
            }
        }
        cout<<"! "<<maxid<<" "<<ansid<<endl;
    }
    return 0;
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值