CodeForces 1776C Library game

发布时间 2023-07-23 18:03:19作者: zltzlt

洛谷传送门

CF 传送门

orz p_b_p_b。

下文令 \(a_i\) 为原题面中的 \(x_i\)

拿到题目无从下手,不妨简化一下。

考虑 \(n = 2\) 怎么做。不妨设 \(a_1 \ge a_2\)。发现若 \(a_2 \le \left\lfloor\frac{m}{2}\right\rfloor\) 时 A 必胜,否则 B 必胜。

于是我们大胆猜测结论是将 \(a\) 从大到小排序后,\(\forall i \in [2, n], a_i \le \left\lfloor\frac{m}{i}\right\rfloor\) 时 A 必胜,否则 B 必胜。

证明是容易的。根据抽屉原理,第 \(i\) 轮开始前不包含选过的元素的极长连续段长度的最大值最小是 \(\left\lceil\frac{m - i + 1}{i}\right\rceil = \left\lfloor\frac{m}{i}\right\rfloor\)。因此:

  • 如果不满足 \(\forall i \in [2, n], a_i \le \left\lfloor\frac{m}{i}\right\rfloor\),设 \(p\) 为使得 \(a_p > \left\lfloor\frac{m}{i}\right\rfloor\) 的位置,那么 A 选择长度 \(\ge a_p\) 的区间时,Bob 一定可以在这个区间内找到 \([1, m]\)\(a_p\) 等分点(即 \(a_p \mid x\) 的点),这样 A 选完 \([1, p]\) 的区间后,B 一定能获胜。
  • 否则,第 \(i\) 轮 A 随便选一个长度 \(= a_i\) 的未被覆盖的区间即可。因为满足 \(\forall i \in [2, n], a_i \le \left\lfloor\frac{m}{i}\right\rfloor\),所以第 \(i\) 轮一定存在一个长度 \(= a_i\) 的未被覆盖的区间。

交互就直接按上面模拟即可。

code
// Problem: C. Library game
// Contest: Codeforces - SWERC 2022-2023 - Online Mirror (Unrated, ICPC Rules, Teams Preferred)
// URL: https://codeforces.com/problemset/problem/1776/C
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;
typedef pair<int, int> pii;

const int maxn = 5050;

int n, m, a[maxn];

namespace Sub1 {
	struct cmp {
		inline bool operator () (const pii &a, const pii &b) {
			return a.scd - a.fst > b.scd - b.fst;
		}
	};
	
	void solve() {
		puts("Alessia");
		fflush(stdout);
		multiset<pii, cmp> st;
		st.emplace(1, m);
		for (int i = 1; i <= n; ++i) {
			pii p = *st.begin();
			int l = p.fst, r = p.scd;
			st.erase(st.begin());
			printf("%d %d\n", a[i], l);
			fflush(stdout);
			int x;
			scanf("%d", &x);
			if (l < x) {
				st.emplace(l, x - 1);
			}
			if (x < r) {
				st.emplace(x + 1, r);
			}
		}
	}
}

namespace Sub2 {
	bool vis[maxn];
	
	void solve() {
		puts("Bernardo");
		fflush(stdout);
		int p = -1;
		for (int i = 1; i <= n; ++i) {
			if (a[i] > m / i) {
				p = i;
				break;
			}
		}
		for (int i = 1, l, r; i <= n; ++i) {
			scanf("%d%d", &r, &l);
			r += l - 1;
			int len = r - l + 1;
			if (len < a[p]) {
				printf("%d\n", l);
				fflush(stdout);
				vis[l] = 1;
				continue;
			}
			for (int j = l; j <= r; ++j) {
				if (j % a[p] == 0) {
					printf("%d\n", j);
					fflush(stdout);
					vis[j] = 1;
					break;
				}
			}
		}
	}
}

void solve() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; ++i) {
		scanf("%d", &a[i]);
	}
	sort(a + 1, a + n + 1, greater<int>());
	bool flag = 1;
	for (int i = 1; i <= n; ++i) {
		if (a[i] > m / i) {
			flag = 0;
			break;
		}
	}
	if (flag) {
		Sub1::solve();
	} else {
		Sub2::solve();
	}
}

int main() {
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}