• CodeChef


    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
    ");
            fflush(stdout);
            scanf("%d",&mp[1]);
            printf("1 %d
    ",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
    ",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-k+1);
                fflush(stdout);
                scanf("%d",&mp[n-k+1]);
            }
            if(mp[n-k+1]!=mp[n]){
                printf("2 %d
    ",mp[n]);
                fflush(stdout);
                continue;
            }
            if(!mp[n-k]){
                printf("1 %d
    ",n-k);
                fflush(stdout);
                scanf("%d",&mp[n-k]);
            }
            if(mp[n-k]==mp[n]){
                printf("2 %d
    ",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
    ",m-(m-1)%k);
                    fflush(stdout);
                    scanf("%d",&mp[m-(m-1)%k]);
                }
                if(!mp[m-(m-1)%k+k-1]){
                    printf("1 %d
    ",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
    ",ans);
            fflush(stdout);
        }
        return 0;
    }
  • 相关阅读:
    C++如何调用父类中的方法
    关于QStandardItemMode的资料
    Qt的信号和槽的使用方法练习
    Redirecting Standard I/O to Windows Console
    C++头文件的工作原理
    《深入浅出MFC》第七章 简单而完整:MFC骨干程序
    《深入浅出MFC》第六章 MFC程序的生死因果
    《深入浅出MFC》第五章 总观Application Framework
    《深入浅出MFC》第四章 Visual C++集成开发环境
    nexus使用记录
  • 原文地址:https://www.cnblogs.com/yzm10/p/9751859.html
Copyright © 2020-2023  润新知