zoukankan      html  css  js  c++  java
  • 【CF809B】Glad to see you!(二分交互题)

    点此看题面

    大致题意: 交互题。已知在一个长度为(n)的序列中选中了(k)个位置,你每次可以询问两个位置(x,y),则若(|x-a|le |y-b|)(a,b)(k)个被选中的位置中分别离(x,y)最近的位置),返回(TAK),否则返回(NIE)。你需要在(60)次询问内求出任意两个被选中的位置并输出。(其实k根本没啥用

    前言

    猛然惊觉叶老师给的题单里面居然还有交互题。

    交互题这么有趣,不写白不写,白写谁不写?

    二分

    (60)次询问,一看就是(log)级别的,一下就能想到二分。而且看数据范围,(60)次询问大概足够二分(3)轮了。

    那我们来考虑怎么二分。

    假设我们已知在区间([l,r])中有被选中的位置,则我们询问([mid,mid+1])

    若返回(TAK),说明在区间([l,mid])中必然有被选中的位置,否则说明在区间([mid+1,r])中必然有被选中的位置。

    按这样二分,只需一轮下来我们就能求出一个位置了。

    然后考虑怎么求第二个位置,显然不能再按上面的套路了,否则只会得到一个完全一样的结果。

    设第一个答案为(t1),如果我们在([1,t1-1])中以同样的方式进行一轮二分,不就可以得出一个异于(t1)的新答案了吗?

    然而,如果([1,t1-1])中并没有答案呢?

    别着急,这就是题目给我们二分(3)轮的次数的原因。如果([1,t1-1])中没有答案,我们就到([t1+1,n])中再进行第三轮二分,这样就肯定能求出另一个答案了。

    整理下上面的思路,最后再讲一个细节问题:如何判断([1,t1-1])中没有答案。

    对于在([1,t1-1])中二分出的结果(t2),如果(t2=t1),或者询问(t2,t1)得到(NIE)(因为对于(t1)来说最近距离为(0),得到(NIE)说明(t2)最近距离大于(0),即其本身并非答案),就说明(t2)是个伪答案。

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define write(op,x,y) (printf("%d %d %d
    ",op,x,y),fflush(stdout))//交互输出
    #define Check() (scanf("%s",s+1),s[1]=='T')//读入结果
    using namespace std;
    int n,k;char s[10];
    I int Solve(RI l,RI r)//二分
    {
    	RI mid;W(l<r) mid=l+r>>1,write(1,mid,mid+1),
    		scanf("%s",s+1),s[1]=='T'?r=mid:l=mid+1;return l;
    }
    int main()
    {
    	scanf("%d%d",&n,&k);RI t1,t2;t1=Solve(1,n),//求出第一个答案
    	((t2=Solve(1,t1-1))==t1||!(write(1,t2,t1),Check()))&&(t2=Solve(t1+1,n));//求出第二个答案
    	return write(2,t1,t2),0;
    }
    
  • 相关阅读:
    jQuery及javascript DOM创建节点(三)
    jQueryEasyUI Window的基本使用
    3.1、值类型
    手动依赖注入(二)
    3.1.2、字符类型
    不错不错
    我们应该讨论什么? 就面向对象的讨论所引发的一些思考
    保存个地址, 顺便问个问题~
    嗯嗯, 今天很高兴
    方法级AOP: 又一个补丁
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/CF809B.html
Copyright © 2011-2022 走看看