1. 程式人生 > >CodeChef - ELHIDARR Find an element in hidden array(二分交互)

CodeChef - ELHIDARR Find an element in hidden array(二分交互)

int num total ble test case rds more program mos

Find an element in hidden array

There is an array of length N consisting of non-negative integers. The array is sorted in non-decreasing order. Each number in the array appears exactly K times, except one element, which appears at least once, but less than K times. Your task is to identify that element.

This is an interactive problem. You are only given the integer N in the input. Both the array and the value of K are hidden. You are allowed to ask the judge the following queries: What is the value of the element at index i of the array? Identify the value of the element with frequency less than K

by asking at most 60 such queries.

Input and Output

The first line of the input contains a single integer T denoting the number of test cases.

For each test case, you should start by reading a single line containing one integer N from the input.

You can interact with the judge using the standard input and output. There are two types of operations: to perform one operation, you should print to the standard output a line containing two space-separated integers type

and val.

  • If type = 1, you are asking the judge a query for the value of the element of the array at index val. After printing this line, the judge will print to the standard input a line containing one integer corresponding to the value of the element at index val.
  • If type = 2, you are telling the judge that the element with frequency less than K is val. For each test case, you should perform this operation exactly once at the end. This is not counted towards the 60 queries.

Note

Don‘t forget to flush the standard output after printing each line. It can be done using fflush(stdout) in C/C++, System.out.flush() in Java and sys.out.flush() in Python.

If you ask more than 60 queries, your program will get the verdict Wrong Answer.

Constraints

  • 1 ≤ T ≤ 104
  • 3 ≤ N ≤ 105
  • 2 ≤ K ≤ N - 1
  • each element of the array lies between 1 and 109 inclusive

Example

Input / judge feedback	your output
1
3
						1 2
1
						1 3
5
						1 1
1
						2 5

Explanation

Example case 1: Suppose the array is [1, 1, 5]. Note that the value of K is 2, but it is hidden from you.

In the first query, you request the value of the 2nd element and the judge answers 1. Then you request the value of the 3rd element and the judge answers 5, then the value of the first element and the judge answers 1.

Now, you tell the judge that the answer is 5. You made a total of 3 queries.

題意:有一個由非負整數組成的長度n的數組。數組按非遞減順序排序。數組中的每個數字恰好出現k次,除了一個元素,至少出現一次,但小於k次。你的任務是識別那個元素。

第一次做交互的題。剛拿到題目有點懵比。。因為它並不是我們習慣的輸入輸出格式,需要先輸出再輸入。

輸出的是向計算機詢問的數值下標,輸入的是計算機回答的數值元素(註意加入fflush(stdout);)。很鍛煉逆向思維。

因為題目限制了在60次內找出value,因此容易想到二分,並用map加以記錄。先找到中間值再找出頭部位置,看是否位於m%k==1的位置,開始用了二分嵌套WA(超出次數)。

後來想到只用一層二分,找出理論上的頭尾部位置(所在位置相距k-1),並比較其值是否相同即可判斷打破規律的元素群在左邊還是在右邊。

#include<bits/stdc++.h>
#define MAX 100005
#define INF 0x3f3f3f3f
using namespace std;

map<int,int> mp;

int main()
{
    int t,n,i,j;
    scanf("%d",&t);
    while(t--){
        mp.clear();
        scanf("%d",&n);
        printf("1 1\n");
        fflush(stdout);
        scanf("%d",&mp[1]);
        printf("1 %d\n",n);
        fflush(stdout);
        scanf("%d",&mp[n]);
        int l=1,r=n,m;
        int k=0;
        while(l<=r){
            m=(l+r)/2;
            if(!mp[m]){
                printf("1 %d\n",m);
                fflush(stdout);
                scanf("%d",&mp[m]);
            }
            if(mp[1]<mp[m]) r=m-1;
            else{
                k=max(k,m);
                l=m+1;
            }
        }
        if(!mp[n-k+1]){
            printf("1 %d\n",n-k+1);
            fflush(stdout);
            scanf("%d",&mp[n-k+1]);
        }
        if(mp[n-k+1]!=mp[n]){
            printf("2 %d\n",mp[n]);
            fflush(stdout);
            continue;
        }
        if(!mp[n-k]){
            printf("1 %d\n",n-k);
            fflush(stdout);
            scanf("%d",&mp[n-k]);
        }
        if(mp[n-k]==mp[n]){
            printf("2 %d\n",mp[1]);
            fflush(stdout);
            continue;
        }
        int ans=INF;
        l=1+k,r=n-k;
        while(l<=r){
            m=(l+r)/2;
            if(!mp[m-(m-1)%k]){
                printf("1 %d\n",m-(m-1)%k);
                fflush(stdout);
                scanf("%d",&mp[m-(m-1)%k]);
            }
            if(!mp[m-(m-1)%k+k-1]){
                printf("1 %d\n",m-(m-1)%k+k-1);
                fflush(stdout);
                scanf("%d",&mp[m-(m-1)%k+k-1]);
            }
            if(mp[m-(m-1)%k]==mp[m-(m-1)%k+k-1]){
                l=m+1;
            }
            else{
                ans=min(ans,mp[m-(m-1)%k]);
                r=m-1;
            }
        }
        printf("2 %d\n",ans);
        fflush(stdout);
    }
    return 0;
}

CodeChef - ELHIDARR Find an element in hidden array(二分交互)