Submission #152445

# Submission time Handle Problem Language Result Execution time Memory
152445 2019-09-08T03:21:01 Z qkxwsm The Big Prize (IOI17_prize) C++14
0 / 100
1000 ms 11312 KB
#include "prize.h"
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>

using namespace std;
using namespace __gnu_pbds;

template<class T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

template<class T, class U>
void ckmin(T &a, U b)
{
	if (a > b) a = b;
}
template<class T, class U>
void ckmax(T &a, U b)
{
	if (a < b) a = b;
}

#define MP make_pair
#define PB push_back
#define LB lower_bound
#define UB upper_bound
#define fi first
#define se second
#define FOR(i, a, b) for (auto i = (a); i < (b); i++)
#define FORD(i, a, b) for (auto i = (a) - 1; i >= (b); i--)
#define SZ(x) ((int) ((x).size()))
#define ALL(x) (x).begin(), (x).end()
#define MAXN 200013

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<pii> vpi;
typedef vector<pll> vpl;

int N;
pii dp[MAXN];
ordered_set<int> cand;
int ans = -1, rec = 0;

pii query(int idx)
{
	if (dp[idx] != MP(-1, -1)) return dp[idx];
	vi tmp = ask(idx);
	dp[idx] = {tmp[0], tmp[1]};
	if (dp[idx] == MP(0, 0)) ans = idx;
	return dp[idx];
}

int find_best(int n)
{
	// return 0;
	N = n;
	if (N == 1) return 0;
	FOR(i, 0, N) dp[i] = {-1, -1};
	int pos = -1;
	FOR(i, 0, min(N, 448))
	{
		pii p = query(i); if (ans != -1) return ans;
		if (pos == -1 || p.fi + p.se > dp[pos].fi + dp[pos].se) pos = i;
	}
	rec = dp[pos].fi + dp[pos].se;
	FOR(i, pos, N) cand.insert(i);
	//find the last guy that still matches it.
	while(true)
	{
		pii p = query(pos);
		//find the last guy that's == pos
		int i = 0;
		for (;; i++)
		{
			if ((1 << i) >= SZ(cand)) break;
			int cur = *cand.find_by_order((1 << i));
			pii q = query(cur); if (ans != -1) return ans;
			if (p != q) break;
			//find the block that's >= pos
		}
		int lo = 0, hi = min(SZ(cand), (1 << i)) - 1;
		while(hi > lo)
		{
			int mid = (hi + lo) >> 1;
			int cur = *cand.find_by_order(mid);
			pii q = query(cur); if (ans != -1) return ans;
			if (p != q) hi = mid - 1;
			else lo = mid;
		}
		pos = *cand.find_by_order(lo) + 1;
		FOR(i, 0, lo + 1)
		{
			cand.erase(cand.begin());
		}
		while(true)
		{
			pii p = query(pos); if (ans != -1) return ans;
			if (p.fi + p.se == rec) break;
			cand.erase(cand.begin()); pos++;
		}
	}
	//pos is an example of the least worth guy.
	//so each time you just want to find an example of any guy worth more than it.
}
# Verdict Execution time Memory Grader output
1 Correct 143 ms 11208 KB Output is correct
2 Execution timed out 3052 ms 11228 KB Time limit exceeded
3 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 145 ms 11252 KB Output is correct
2 Execution timed out 3062 ms 11312 KB Time limit exceeded
3 Halted 0 ms 0 KB -