P13309 演剧

P13309 演剧

题意

A 和 B 在玩游戏。

给你一个长度为 \(n\) 的序列。A 先手。

每一轮,先手会选择一个切割点,把序列分成两份。然后后手选择留下其中一部分。然后交换先后手。

最后只剩下一个数字的时候,游戏结束。

A 希望剩下的数字尽可能大,B 希望剩下的数字尽可能小。

求剩下的数字。

\(n \le 10^5\)

思路

参考了出题人题解。

想试试我能不能把我的想法有理有据的讲出来。


除了 A 先手之外,其他条件都是完全公平的。

于是我们大胆猜测留下来的一定是中位数。(序列长度为偶数时,我们认为有两个中位数)


我们试着证明无论哪个人先手,都不能取到比中位数大的数字。(求比中位数小的数是对称的)

钦定比中位数大的数字的权值是 +1,其他是 -1

序列为偶数时,我们可以加一个 \(inf\) 变成序列为奇数的情况,不影响比中位数排名加一的数字。因此考虑序列为奇数的情况。

当 A 先手时,它一定可以把序列分成两份,其中一份的权值和是 -1,另一份的权值和是 0。B 选择 -1 的那份。下一轮,B 把序列分成 -10,A 选择 0

因此最后只剩下一个数字的时候,权值一定是 -1

证毕。


现在只需要求出,对于序列长度为偶数,且两个中位数不相等的情况,答案是哪个中位数。

较小的中位数为 \(x_1\),较大的中位数为 \(x_2\)

钦定 \(\ge x_2\) 的数字权值为 \(1\),其他数字权值为 \(-1\)

什么时候可以取到 1

考虑一个极端情况(为了好看,这里把 -1 写作 0):0000011111

A 先手,把序列分成 000001111 1

B 选择前者。然后把序列分成 0 00001111

这种情况不能取到 1

对于序列 0001010111 之类,也是同样结果。

对于这类序列,先手不得不把它分成权值和为 -11 两部分。后手有选择其中一个的权力,因此先手必输。

即,对于一个长度极小的,权值和为 0 的序列,先手必输。

对于还能分成若干个权值和为 0 的序列,先手会把序列分成 00

假设原序列可以分成两个极小 0 序列。那么后手输。

假设原序列可以分成三个极小 0 序列,那么左边有一个极小 0 序列,右边有两个极小 0 序列,后手选择左边,然后先手输。

假设原序列可以分成四个极小 0 序列,因为 1、3 必输,所以先手必胜。

因此假设原序列可以分成 \(cnt\) 个极小 0 序列。\(cnt\) 奇数时先手输,偶数时先手赢。

code

使用 nth_element() 函数可以做到平均 \(O(n)\)

#include<bits/stdc++.h>
#define sf scanf
#define pf printf
#define rep(x,y,z) for(int x=y;x<=z;x++)
#define per(x,y,z) for(int x=y;x>=z;x--)
using namespace std;
typedef long long ll;
namespace wing_heart {
	constexpr int N=1e5+7;
	int T;
	int n,a[N],b[N];
	void main() {
		sf("%d",&T);
		while(T--) {
			sf("%d",&n);
			rep(i,1,n) sf("%d",&a[i]);
			memcpy(b,a,sizeof(b));
			if(n&1) {
				nth_element(b+1,b+(n>>1)+1,b+n+1);
				int x = b[(n>>1)+1];
				pf("%d\n",x);
			} else {
				nth_element(b+1,b+(n>>1),b+n+1);
				int x1 = b[n>>1];
				nth_element(b+1,b+(n>>1)+1,b+n+1);
				int x2 = b[(n>>1)+1];
				int cnt=0, sum=0;
				if(x1==x2) pf("%d\n",x1); 
				else {
					rep(i,1,n) {
						if(a[i]>=x2) sum++;
						else sum--;
						if(sum==0) ++cnt;
					}
					if(cnt&1) pf("%d\n",x1);
					else pf("%d\n",x2);
				}
			}
		}
	}
}
int main() {
	#ifdef LOCAL
	freopen("in.txt","r",stdin);
	freopen("my.out","w",stdout);
	#endif
	wing_heart :: main();
}
posted @ 2025-11-13 10:39  wing_heart  阅读(6)  评论(0)    收藏  举报