Submission #637620

#TimeUsernameProblemLanguageResultExecution timeMemory
637620boris_mihovThe Big Prize (IOI17_prize)C++17
90 / 100
85 ms1920 KiB
#include "prize.h"
#include <algorithm>
#include <iostream>
#include <cassert>
#include <numeric>
#include <vector>

typedef long long llong;
const int MAXN = 200000 + 10;
const int INF  = 1e9;

int ans, n;
std::vector <int> res;
std::pair <int,int> asked[MAXN];
inline std::pair <int,int> query(int pos)
{
    assert(1 <= pos && pos <= n);
    if (asked[pos].first != -1) return asked[pos];
    res = ask(pos - 1);
    asked[pos] = {res[0], res[1]};
    if (res[0] == 0 && res[1] == 0) ans = pos;
    return asked[pos];
}

int leftCnt;
int rightCnt;
int cntBig;
int binaryCnt;

int binarySearchLeft(int from, int to)
{
    int l = from, r = to, mid;
    while (l < r - 1)
    {
        mid = (l + r) / 2;
        auto [left, right] = query(mid);
        if (ans != 0) return 0;
        if (left + right != cntBig)
        {
            r = mid;
            continue;
        }

        if (left != leftCnt)
        {
            r = mid;
            continue;
        }

        l = mid;
    }

    query(r);
    leftCnt++;
    return r;
}

int binarySearchRight(int from, int to)
{
    int l = from, r = to, mid;
    while (l < r - 1)
    {
        mid = (l + r) / 2;
        auto [left, right] = query(mid);
        if (ans != 0) return 0;
        if (left + right != cntBig)
        {
            l = mid;
            continue;
        }

        if (right != rightCnt)
        {
            l = mid;
            continue;
        }

        r = mid;
    }

    query(l);
    rightCnt++;
    return l;
}

int find_best(int N) 
{
    n = N;
	srand(6686889);
    std::fill(asked + 1, asked + 1 + n, std::make_pair(-1, -1));
    for (int i = 1 ; i <= std::min(n, 500) ; ++i)
    {
        query(i);
        cntBig = std::max(cntBig, asked[i].first + asked[i].second);
    }

    if (ans != 0) return ans - 1;
    for (int i = 1 ; i <= 500 ; ++i)    
    {
        leftCnt += (asked[i].first + asked[i].second != cntBig);
    }

    int l = 447, r = n + 1;
    while (ans == 0 && l < r - 1)
    {
        if (rand()%2 == 0) l = binarySearchLeft(l, r);
        else               r = binarySearchRight(l, r);
    }

    if (ans == 0 && l != 0) query(l);
    if (ans == 0 && r != n + 1) query(r);
    assert(asked[ans].first == 0 && asked[ans].second == 0);
    return ans - 1;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...