CodeChef

题意:有一串不递减的串,串中的任意元素都有k个,除了一个元素,他只有1 <= n < k-1个,你现在能向oj做出以下操作:

输出:1 pos,oj会返回pos位置的元素值

输出:2 val,回答那个特殊的元素是什么值

要求不能询问超过60次,给出特殊元素的值。

思路:先第一次二分找出k。可以想出,k * m和k * m + 1如果不同,那么k * m之前的数肯定没有特殊元素,反之则有,那么我们就找出第一个k * m == k * m + 1的地方,这之前的元素就是特殊元素。

每次printf之后都要加一句fflsh(stdout),否则TLE伺候。

代码:

#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
typedef long long ll;
using namespace std;
const int maxn = 1e5 + 10;
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
int val[maxn];
bool vis[maxn];
int T, n, k;
int get(int pos){
    if(pos > n || pos < 1) return -1;
    if(!vis[pos]){
        int b;
        printf("1 %d
", pos);
        fflush(stdout);
        scanf("%d", &b);
        val[pos] = b;
        return b;
    }
    else{
        return val[pos];
    }
}
int main(){
    scanf("%d", &T);
    while(T--){
       memset(vis, false, sizeof(vis));
       scanf("%d", &n);
       int a, b;
       a = get(1);
       int l = 1, r = n, ans;
       while(l <= r){
            int m = (l + r) >> 1;
            int c = get(m);
            if(c == a) ans = m;
            if(c != a) r = m - 1;
            else l = m + 1;
       }
       k = ans;
       if(get(k + 1) == get(2 * k + 1)){
            printf("2 %d
", get(1));
            fflush(stdout);
       }
       else{
            l = 1, r = n / k + 1;
            while(l <= r){
                int m = (l + r) >> 1;
                if(get(k * m) != get(k * m + 1)){
                    l = m + 1;
                    ans = m + 1;
                }
                else{
                    r = m - 1;
                }
            }
            printf("2 %d
", get((ans - 1) * k + 1));
            fflush(stdout);
       }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/KirinSB/p/10290290.html