码迷,mamicode.com
首页 > 其他好文 > 详细

【ARC122D】XOR Game

时间:2021-06-13 10:57:23      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:math   题目   ref   假设   最优   return   main   pre   min   

题目

题目链接:https://atcoder.jp/contests/arc122/tasks/arc122_d
给定一个长度为 \(2n\) 的序列,Alice 和 Bob 执行以下操作 \(n\) 次:

  • Alice 选择一个之前未被选择过的数字 \(x\)
  • Bob 选择一个之前未被选择过的数字 \(y\)
  • 这一轮的价值为 \(x\text{ xor } y\)

\(n\) 轮后总价值为每一轮价值的最大值。Alice 想最大化总价值,Bob 想最小化总价值。在两人都选择最优策略的情况下,求最后总价值是多少。
\(n\leq 2\times 10^5;0\leq a_i<2^{30}\)

思路

我们首先考虑二进制下最高位。假设这 \(2n\) 个数字二进制下最高位为 \(0\) 的有偶数个(显然为 \(1\) 的也有偶数个),那么 Bob 肯定是让 \(0\)\(0\) 匹配,\(1\)\(1\) 匹配。分成两部分继续考虑次高位,此时原问题变为了两个子问题。
如果这 \(2n\) 个数字二进制下最高位为 \(0\) 的有奇数个,那么显然在这一位无论怎么匹配最大值都是 \(1\)。直接找出异或和最小的两个让他们匹配显然是 Bob 的最优策略。用 Trie 实现即可。
所以其实这道题 Alice 只不过是一个工具人罢了。
时间复杂度 \(O(n\log n)\)

代码

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

const int N=400010,LG=29,Inf=2147483647;
int n,a[N];

struct Trie
{
	int tot,ch[N*LG][2];
	
	void clear()
	{
		for (int i=0;i<=tot;i++)
			ch[i][0]=ch[i][1]=0;
		tot=1;
	}
	
	void ins(int v)
	{
		int p=1;
		for (int i=LG;i>=0;i--)
		{
			int id=(v>>i)&1;
			if (!ch[p][id]) ch[p][id]=++tot;
			p=ch[p][id];
		}
	}
	
	int query(int v)
	{
		int ans=0,p=1;
		for (int i=LG;i>=0;i--)
		{
			int id=(v>>i)&1;
			if (ch[p][id]) p=ch[p][id];
				else ans+=(1<<i),p=ch[p][id^1];
		}
		return ans;
	}
}trie;

int solve(int l,int r,int dep)
{
	if (dep<0 || l>r) return 0;
	int k=l-1,ans=Inf;
	while (k<r && !(a[k+1]&(1<<dep))) k++;
	if ((k-l)&1) return max(solve(l,k,dep-1),solve(k+1,r,dep-1));
	trie.clear();
	for (int i=l;i<=k;i++) trie.ins(a[i]);
	for (int i=k+1;i<=r;i++) ans=min(ans,trie.query(a[i]));
	return ans;
}

int main()
{
	scanf("%d",&n); n<<=1;
	for (int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	sort(a+1,a+1+n);
	cout<<solve(1,n,LG);
	return 0;
}

【ARC122D】XOR Game

标签:math   题目   ref   假设   最优   return   main   pre   min   

原文地址:https://www.cnblogs.com/stoorz/p/14879394.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!