[ARC116] Deque Game

一、题目

点此看题

请先阅读题目描述再看题解。

(k) 个序列,第 (i) 个队列 (A_i) 的长度为 (n_i)

阿七和十三要玩游戏,阿七先手,他们轮流操作,每次选择一个长度大于 (1) 的删去队首或者删去队尾,直接所有队列长度都为 (1)

最后会剩下 (k) 个元素,阿七想让元素和最大,十三想让元素和最小,他们足够聪明。因为阿七还要和梅小姐去海边,所以他想知道最后的结果会是多少,这个任务就交给了正在看国漫的你。

(1leq k,sum n_ileq 2cdot 10^5,1leq a_{i,j}leq 10^9)

二、解法

subtask1(k=1)

这是一个简化得不能再简化的问题,但是我们还是要弄清楚原理。

如果 (n) 是偶数,那么答案是 (max(a[n/2],a[n/2+1])),证明很巧妙,先手存在策略一定能选到中间二者的最大值,所以答案 (geqmax(a[n/2],a[n/2+1])),同时后手也存在策略逼迫先手选到中间两者的最大值,所以答案 (leqmax(a[n/2],a[n/2+1])),那么只能取等。

如果 (n) 是奇数,类似分析可得答案是 (max(min(a[n/2],a[n/2+1]),min(a[n/2+1],a[n/2+2])))( t max) 是先手决定的,而 (min) 是后手来选取的。

subtask2(n is all odd)

这里解释一下为什么我们要考虑 (n_i) 全是奇数的情况,因为操作偶数长度的队列会交换先后手,而根据答案的计算方式一旦交换先后手是超级麻烦的,(n_i) 全是奇数就不存在先后手交换的问题。

(f(a[1...n])=max(min(a[n/2],a[n/2+1]),min(a[n/2+1],a[n/2+2]))),那么最后的答案是:

[ans=sum_{i=1}^k f(a_i[1...n_i]) ]

现在证明为什么是这个简洁的形式,先证明阿七一定能到这个状态,第一步可以取任意队列,如果十三去操作别的队列,阿七就可以成为后手去操作那个队列,如果某个队列最后剩下了三个,那么十三是不会去操作它的,因为有一个极其重要的式子:

[max(min(a[n/2],a[n/2+1]),min(a[n/2+1],a[n/2+2]))leqmin(max(a[n/2],a[n/2+1]),max(a[n/2+1],a[n/2+2])) ]

前面的算式是十三为后手的答案,后面的算式是十三为先手的答案,因为等式恒成立所以十三会想办法让自己当后手,自然就不会先去操作只剩三个的队列的,所以阿七一定能到这个状态,答案 (geq ans)

证明十三一定能到这个状态是很容易的,只要和阿七一直对称操作即可,答案 (leq ans),综上答案就是 (ans)

subtask3(common situation)

引入偶数队列就有问题了,因为操作完他之后会交换先后手,操作某个偶数队列可以看成将之转化成奇数队列并且十三和阿七交换先后手,如果阿七一开始操作了某个偶数队列,那么十三一定会操作另一个因为她要保持自己的后手地位才更优。

所以如果有奇数个偶数队列,那么十三是真正的先手,如果有偶数个偶数队列,阿七是真正的先手,这会影响到奇数队列的答案计算方式,如果阿七是先手答案是 (max(min(a[n/2],a[n/2+1]),min(a[n/2+1],a[n/2+2]))),十三先手就是另一种。

还有最后一个问题没有考虑,阿七和十三怎么决定自己操作哪些偶数队列?由于两种选择会带来的答案分别是 (x=f(a_i[1....n_i-1]))(y=f([2....n_i])),依照贪心阿七会选 (x,y) 差值最大的 (max(x,y)),十三会选 (x,y) 差值次大的 (min(x,y)),以此类推,搞个优先队列即可解决,时间复杂度 (O(nlog n))

#include <cstdio>
#include <vector>
#include <iostream>
#include <queue>
using namespace std;
const int M = 200005;
#define int long long
int read()
{
	int x=0,f=1;char c;
	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	return x*f;
}
int k,n,m,ans,l[M],a[M];vector<int> v[M];
int f(int t)
{
	if(n==2) return t==0?a[2]:a[1];
	if(!m) return max(min(a[n/2+t],a[n/2+1+t]),min(a[n/2+1+t],a[n/2+2+t]));
	return min(max(a[n/2+t],a[n/2+1+t]),max(a[n/2+1+t],a[n/2+2+t]));
}
signed main()
{
	k=read();
	for(int i=1;i<=k;i++)
	{
		l[i]=read();
		for(int j=1;j<=l[i];j++)
			v[i].push_back(read());
		if(l[i]%2==0) m^=1;
	}
	priority_queue<int> q;
	for(int i=1;i<=k;i++)
	{
		n=l[i];
		for(int j=1;j<=n;j++)
			a[j]=v[i][j-1];
		if(n%2)//odd
		{
			if(n==1) ans+=a[1];
			else ans+=f(0);
		}
		else
		{
			int x1=f(-1),x2=f(0);
			int t1=max(x1,x2),t2=min(x1,x2);
			q.push(t1-t2);ans+=t2;
		}
	}
	while(!q.empty())
	{
		ans+=q.top();q.pop();
		if(!q.empty()) q.pop();
	}
	printf("%lld
",ans);
}
原文地址:https://www.cnblogs.com/C202044zxy/p/14802389.html