[??记录]ARC116F Deque Game
command_block
2021-10-28 10:18:55
**题意** : 给出 $k$ 个序列,第 $i$ 个序列 $S_i$ 的长度为 $n_i$ 。
A 和 B 用这些序列玩游戏,两人轮流进行下列操作,直到所有序列的长度都变为 $1$。
- 删除某个(长度至少为 $2$ 的)序列的开头或结尾。
A 先手。A 想要最大化最终剩下的 $k$ 个元素的和,而 B 想要最小化,求最终这 $k$ 个元素的和。
$k,\sum_i n_i\leq 2\times1 0^5$ ,时限$\texttt{2s}$。
------------
先观察只有一个序列的情况。
记 $f(S)$ 为 $S$ 的答案。
- $n=1$,B 先手:$f(S)=S_1$ 。
- $n=2$,A 先手:$f(S)=\max(S_1,S_2)$ 。
- $n=3$,B 先手:$f(S)=\min\Big(\max(S_1,S_2),\max(S_2,S_3)\Big)=\max(S_2,\min(S_1,S_3))$ 。
- $n=4$,A 先手, :$f(S)=\max\Big(\max(S_2,\min(S_1,S_3)),\max(S_3,\min(S_2,S_4))\Big)=\max(S_2,S_3)$ 。
如此不难归纳证明:
- $n$ 为偶数,A 先手时, $f(S)=\max\big(A_{n/2-1},A_{n/2}\big)$ 。
- $n$ 为奇数,B 先手时, $f(S)=\max\big(A_{(n+1)/2},\min\big(A_{(n+1)/2-1},A_{(n+1)/2+1}\big)\big)$ 。
由于 $\min$ 和 $\max$ 对称,先后手反过来也类似:
- $n$ 为偶数,B 先手时, $f(S)=\min\big(A_{n/2-1},A_{n/2}\big)$ 。
- $n$ 为奇数,A 先手时, $f(S)=\min\big(A_{(n+1)/2},\max\big(A_{(n+1)/2-1},A_{(n+1)/2+1}\big)\big)$ 。
------------
准备工作:比较对于一个序列,先手赚还是后手赚。
- $n$ 为偶数:双方都是先手更赚。
$\max\big(A_{n/2-1},A_{n/2}\big)\geq \min\big(A_{n/2-1},A_{n/2}\big)$
- $n$ 为奇数:双方都是后手更赚。
$\min\big(A_{(n+1)/2},\max\big(A_{(n+1)/2-1},A_{(n+1)/2+1}\big)\big)\leq \max\big(A_{(n+1)/2},\min\big(A_{(n+1)/2-1},A_{(n+1)/2+1}\big)\big)$
因为前者至多是 $A_{(n+1)/2}$ ,后者至少是 $A_{(n+1)/2}$。
接着我们来研究多个序列的情况,可以归纳证明:
- 若所有 $n_i$ 均为奇数,先手操作一次后,会形成一个偶序列,则后手必定接着操作这个偶序列。
答案即为各个序列的答案的和。
- 若存在偶序列,则先手必选一个偶序列操作。
这可以说明两人必定先瓜分完偶序列,然后变为奇数序列的情况。
注意瓜分完之后先后手可能会变化。
对于第 $i$ 个序列,记操作一次后的 $f$ 的较大值(要考虑先后手)为 $a_i$ ,较小值为 $b_i$ 。
若让 A 操作,则会选 $a_i$ ,B 选 $b_i$ 。按照 $a_i-b_i$ 从大到小排序,按这个顺序瓜分。
```cpp
#include<algorithm>
#include<cstdio>
#define ll long long
#define MaxN 200500
using namespace std;
int c1,m,a[MaxN],fA[MaxN],fB[MaxN],gA[MaxN][2],gB[MaxN][2],s[MaxN],tn;
bool e[MaxN];
int main()
{
scanf("%d",&m);
for (int k=1,n;k<=m;k++){
scanf("%d",&n);
for (int i=1;i<=n;i++)scanf("%d",&a[i]);
if (n==1)fA[k]=fB[k]=a[1];
else if (n&1){
int mid=(n+1)/2;
fA[k]=min(a[mid],max(a[mid-1],a[mid+1]));
fB[k]=max(a[mid],min(a[mid-1],a[mid+1]));
}else {
c1++;e[k]=1;
int mid=n/2;
fA[k]=max(a[mid],a[mid+1]);
fB[k]=min(a[mid],a[mid+1]);
if (n==2){
gB[k][0]=gA[k][0]=a[1];
gB[k][1]=gA[k][1]=a[2];
}else {
gA[k][0]=min(a[mid],max(a[mid-1],a[mid+1]));
gB[k][0]=max(a[mid],min(a[mid-1],a[mid+1]));
mid++;
gA[k][1]=min(a[mid],max(a[mid-1],a[mid+1]));
gB[k][1]=max(a[mid],min(a[mid-1],a[mid+1]));
}
}
}
ll ans=0;
for (int i=1;i<=m;i++)if (e[i]){
int a,b;
if (c1&1){a=gB[i][0];b=gB[i][1];}
else {a=gA[i][0];b=gA[i][1];}
if (a<b)swap(a,b);
ans+=b;s[++tn]=a-b;
}else {if (c1&1)ans+=fB[i];else ans+=fA[i];}
sort(s+1,s+tn+1);
for (int i=tn;i>=1;i-=2)ans+=s[i];
printf("%lld",ans);
return 0;
}
```