专栏文章

题解:P12360 [eJOI 2024] 足球决斗 / CF Duels

P12360题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mipg4qxf
此快照首次捕获于
2025/12/03 11:27
3 个月前
此快照最后确认于
2025/12/03 11:27
3 个月前
查看原文
显然得到的信息越多越容易确定胜利,因此答案具有单调性,考虑二分并检验得到信息的场馆数量 midmid
因为我们可以在比赛开始后再安排双方球员的对阵关系,所以不确定性来源于一对对阵取得的收益来自哪个场馆不确定。然后就是经典的田忌赛马策略:将双方球员和场馆按权值升序排列,逐一考虑己方队员,考虑他能战胜的所有对手并分情况讨论。若选择的对手来自已知的场馆那么收益是确定的,这种情况容易处理。若选择的对手来自未知的场馆,则取其中的最小收益累加。考虑完所有球员后判断能否取得冠军。若最小收益足以战胜对手则说明能否获胜与对方的安排无关,可以必胜,因为我们考虑了对方采取最佳的安排将我方收益最小化时的情况。
用一个大根堆维护所有可能的对阵情况,每次取出堆顶对阵方案即可。
CPP
const ll N = 5e4 + 10;
ll n, sum, a[N], v[N];
pll sta[N], player[N];
pqueue(ll, less) pq;

#define jump1 for(;a[i]>player[p1].fi and p1<=n;p1++)
#define jump2 while(sta[p2].se<=k and p2<=n)p2++;

bool check(ll k) {
	myclear(pq);
	ll pts = 0, p1 = 1, p2 = 1;
	jump2;

	rep(i, 1, n) {
		jump1{
			if (player[p1].se <= k)
				pq.push(v[player[p1].se]);
			else {
				pq.push(sta[p2].fi);
				p2++;
				jump2;
			}
		}

		if (pq.size()) {
			pts += pq.top();
			pq.pop();
		}
	}

//	cout << "pts=" << pts << '\n';
//	pause;
	return pts > sum - pts;
}

int main() {
	cin >> n;

	rep(i, 1, n) {
		cin >> v[i];
		sta[i] = {v[i], i};
		sum += v[i];
	}

	sort(sta + 1, sta + n + 1);

	rep(i, 1, n) {
		cin >> player[i].fi;
		player[i].se = i;
	}

	sort(player + 1, player + n + 1);

	rep(i, 1, n) cin >> a[i];

	sort(a + 1, a + n + 1);

	ll l = 0, r = n, ans = -1;

	while (l <= r) {
		ll mid = (l + r) / 2;

		if (check(mid)) {
			ans = mid;
			r = mid - 1;
		} else
			l = mid + 1;
	}

	cout << ans;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...