ARC116F - Deque Game

\(k\)个序列。A和B在博弈,A先手。每次可以选择一个长度大于\(1\)的序列,把头或尾丢掉。

A希望最终和最大,B希望最终和最小。

\(k\le 2*10^5,\sum len_i\le 2*10^5\)


跟我出过的题好像呢。

用类似那题的思路,首先思考一个奇数长度序列怎么做:

\(len=3\)时,枚举一下,答案显然为\(\min(a_2,\max(a_1,a_3))\)

猜想\(\min(a_{mid},\max(a_{mid-1},a_{mid+1}))\)。归纳一下:
\(len>3\)时,如果A选了开头,B能得到:\(\min(\min(a_{mid+1},\max(a_{mid},a_{mid+2})),\min(a_{mid},\max(a_{mid-1},a_{mid+1})))\)。也就是\(\min(a_{mid},a_{mid+1})\)。A选结尾类似。所以A能得到\(\max(\min(a_{mid},a_{mid+1}),min(a_{mid},a_{mid-1}))=\min(a_{mid},\max(a_{mid-1},a_{mid+1}))\)

再考虑偶数序列,由于这里有点奇怪需要讨论。

当偶数序列个数为偶数时:一开始每个偶数序列操作一次,最后变成全是奇数序列。把偶数序列操作完之后先后手顺序不变。如果在偶数序列被操作前操作了奇数序列,那么可以跟着操作,必然会发展会上述奇数序列的情况。所以操作奇数序列不优。

当偶数序列个数为奇数时:也是要先操作前偶数序列。如果先操作偶数序列,再操作奇数序列,那么对于一个奇数序列它的权值是\(\max(a_{mid},\min(a_{mid-1},a_{mid+1}))\)。如果先操作了奇数序列,后手可以相反方向操作,使得最终权值只能是\(a_{mid}\),由于权值不会变得更大所以操作奇数序列会亏。(上面的情况大概也能这么解释)

综上都是先轮流操作偶数序列将它们变成奇数序列,再操作奇数序列。操作偶数序列的时候贪心一下。


using namespace std;
#include <bits/stdc++.h>
#define N 200005
#define ll long long
int n;
vector<int> a[N];
int q[N],nq;
int main(){
//	freopen("in.txt","r",stdin);
	scanf("%d",&n);
	int cnt=0;
	for (int i=0;i<n;++i){
		int k;
		scanf("%d",&k);
		for (int j=0,x;j<k;++j)
			scanf("%d",&x),a[i].push_back(x);
		cnt+=(k&1^1);
	}
	ll sum=0;
	for (int i=0;i<n;++i)
		if (a[i].size()&1^1){
			if (a[i].size()==2){
				sum+=min(a[i][0],a[i][1]);
				q[nq++]=-(max(a[i][0],a[i][1])-min(a[i][0],a[i][1]));
			}
			else{
				int mid0=a[i].size()/2-1,mid1=mid0+1,v0,v1;
				if (cnt&1^1){
					v0=min(a[i][mid0],max(a[i][mid0-1],a[i][mid0+1]));
					v1=min(a[i][mid1],max(a[i][mid1-1],a[i][mid1+1]));
				}
				else{
					v0=max(a[i][mid0],min(a[i][mid0-1],a[i][mid0+1]));
					v1=max(a[i][mid1],min(a[i][mid1-1],a[i][mid1+1]));
				}
				sum+=min(v0,v1);
				q[nq++]=-(max(v0,v1)-min(v0,v1));
			}
		}
	for (int i=0;i<n;++i)
		if (a[i].size()&1){
			if (a[i].size()==1)
				sum+=a[i][0];
			else{
				int mid=a[i].size()/2;
				if (cnt&1^1)
					sum+=min(a[i][mid],max(a[i][mid-1],a[i][mid+1]));
				else
					sum+=max(a[i][mid],min(a[i][mid-1],a[i][mid+1]));
			}
		}
	sort(q,q+nq);
	for (int i=0;i<nq;i+=2)
		sum+=-q[i];
	printf("%lld\n",sum);
	return 0;
}
posted @ 2021-03-29 20:02  jz_597  阅读(174)  评论(0编辑  收藏  举报