题解:CF794E Choosing Carrot

posted on 2024-11-26 11:59:12 | under | source

先不考虑 A 提前拿走数。

注意到后手比较厉害,可以做先手相反的操作使得每一轮恰好两侧的数被扔掉。

\(mid=\frac{l+r}2\)。当 \(2\mid n\) 时,B 可以使得答案 \(\le \max(a_{mid},a_{mid+1})\)。A 可以一开始拿走左侧的然后与 B 做相反操作然后得到 \(a_{mid+1}\)\(a_{mid}\) 同理。故答案为 \(\max(a_{mid},a_{mid+1})\)

上述讨论在 B 先手时是对偶情况,可以推出当 \(2\nmid n\) 时答案是 \(\max(\min(a_{mid-1},a_{mid}),\min(a_{mid},a_{mid+1}))\)。注意 \(n=1\) 的特殊情况。

加入修改,那么就是对所有 \(n-k\) 大小的区间取个 \(\max\),显然有个 \(st\) 表做法,考虑 \(mid\) 的下标范围即可。

但是还有更简单的线性做法,注意到将区间两侧同时缩短 \(1\) 答案不变,那么可以递推,\(k\) 必然可以继承 \(k-2\) 的所有情况(每个区间缩短两侧),然后只需加入两侧的区间答案即可。

复杂度 \(O(n)\)

代码

#include<bits/stdc++.h>
using namespace std;

#define int long long
const int N = 3e5 + 5;
int n, a[N], ans[N], mx;

inline int get(int l, int r){
	int mid = (l + r) >> 1;
	if((r - l) & 1) return max(a[mid], a[mid + 1]);
	return max(min(a[mid - 1], a[mid]), min(a[mid], a[mid + 1])); 
}
signed main(){
	cin >> n;
	for(int i = 1; i <= n; ++i) scanf("%lld", &a[i]), mx = max(mx, a[i]);
	ans[0] = get(1, n);
	ans[1] = max(get(1, n - 1), get(2, n));
	for(int i = 2; i < n - 1; ++i) ans[i] = max(ans[i - 2], max(get(1, n - i), get(i + 1, n)));
	for(int i = 0; i < n; ++i) printf("%lld ", (i < (n - 1)) ? ans[i] : mx); 
	return 0;
}
posted @ 2026-01-15 08:16  Zwi  阅读(1)  评论(0)    收藏  举报