题意: 交互式问题。 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; }