CodeForces 810D Glad to see you! 思维,二分,交互式

CodeForces 810D

题意: 交互式问题。 n 个数,从中取出了 k 个数,你可以询问 60 次。每次询问有 x,y,对于 x 在 k 个数里会有一个最接近 x 的数 a,即 | a-x | 最小,同理对 b 有一个 b 。  如 |a-x| <= |b-y|,则会返回 TAK;否则返回 NIE。   要你最后确定两个数是这k个数里面的。

tags: 好难想到。。。二分,询问 mid 和 mid+1  。

对于区间 [1,n],先二分得到一个符合条件的数 x1,再二分 [1, x1-1] 和 [x1+1, n] 得到另外两个数,在这两个数中选择一个符合的数即可。

这题首先难想,其次二分也有点不好写,但算是好题了。

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
typedef long long ll;
const int N = 200005;

int n, k;
char str[10];
int get(int l, int r)
{
    if(l>r) swap(l, r);
    int mid, ans=l;
    if(l<1) ans=r;
    if(l<1 || n<r) return ans;
    while(l+1<=r)
    {
        mid = l+r>>1;
        cout<<1<<" "<<mid<<" "<<mid+1<<endl;
        scanf("%s", str);
        if(str[0]=='T') r=mid, ans=mid;
        else  l=mid+1, ans=mid+1;
    }
    return ans;
}
int main()
{
    scanf("%d%d", &n, &k);
    int x1 = get(1, n);
    int x2 = get(1, x1-1);
    int x3 = get(x1+1, n);

    if(x2==x1) x2=x3;
    else if(x3!=x1)
    {
        cout<<1<<" "<<x2<<" "<<x3<<endl;
        scanf("%s", str);
        if(str[0]=='N') x2=x3;
    }

    if(x1>x2) swap(x1, x2);
    cout<<2<<" "<<x1<<" "<<x2<<endl;

    return 0;
}
原文地址:https://www.cnblogs.com/sbfhy/p/7689102.html