首页 > 其他分享 >[CF1849F] XOR Partition

[CF1849F] XOR Partition

时间:2023-07-29 20:14:24浏览次数:66  
标签:integers set XOR Partition ch CF1849F oplus 字典

XOR Partition

题目描述

For a set of integers $ S $ , let's define its cost as the minimum value of $ x \oplus y $ among all pairs of different integers from the set (here, $ \oplus $ denotes bitwise XOR). If there are less than two elements in the set, its cost is equal to $ 2^{30} $ .

You are given a set of integers $ {a_1, a_2, \dots, a_n} $ . You have to partition it into two sets $ S_1 $ and $ S_2 $ in such a way that every element of the given set belongs to exactly one of these two sets. The value of the partition is the minimum among the costs of $ S_1 $ and $ S_2 $ .

Find the partition with the maximum possible value.

输入格式

The first line contains $ n $ ( $ 2 \le n \le 200000 $ ) — the number of elements in the set.

The second line contains $ n $ distinct integers $ a_1 $ , $ a_2 $ , ..., $ a_n $ ( $ 0 \le a_i < 2^{30} $ ) — the elements of the set.

妙妙题。

二分出来 \(m\),然后去看 \(a_i\oplus a_j<m\) 的所有 \(i,j\) 是不是组成二分图。明显要黑白染色。

如何知道一个数列中最小的 \(a_x\oplus a_y(x\ne y)\)? 有两种方法,而这两种方法衍生出这题的两种做法。

1,字典树

这个东西可以用字典树求。

考虑用字典树优化暴力建图。在跑字典树的途中,向小于 \(m\) 的所有子树连边,会连 \(\log n\) 次。

但是我不能连向自己所在的节点。所以要前后缀加上可持久化字典树就可以了。复杂度 \(O(nlog^2n)\),这是我考场上想到的方法,但是没写。

这题还有另一个单 log 的字典树做法。但没看懂

2

将 \(a\) 从小到大排序后 \(\min\limits_{i=1}^{n-1} a_i\oplus a_{i+1}\) 就是答案。因为异或存在性质:如果 \(x<y<z\),则 \(\min(x\oplus y,y\oplus z)<x\oplus z\)

这里也一样,将 \(a\) 从小到大排序后,如果 \(a_i\oplus a_{i+j}<m(j\ge 4)\),那么一定无解。考虑 $a_{i}\oplus a_{i+j} $ 的最高位,中间夹的这五个数可能是 \(\{0,0,0,0,1\},\{0,0,0,1,1\},\{0,0,1,1,1\},\{0,1,1,1,1\}\),然后这五种都存在三元环。

考虑一个 \(a_i\),我们只让他和 \(a_{i+1},a_{i+2},a_{i+3}\) 去连边。但是这样好像还是会有一个问题,如何证明这样连边合法的情况下,不存在连了后面的边后才会出现非法情况。但是这样做是能过的。希望有大佬可以给个证明或 hack。OI比赛中还是打 Trie 计算除了前三个是否存在 \(a_i\oplus a_j<m\) 或者打拍比较保险。

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,m,a[N],col[N],fl,e_num,hd[N],l=1,r=(1<<30)-1,id[N],p[N];
struct edge{
	int v,nxt;
}e[N<<3];
void add_edge(int u,int v)
{
	e[++e_num]=(edge){v,hd[u]};
	hd[u]=e_num;
}
int read()
{
	int s=0;
	char ch=getchar();
	while(ch<'0'||ch>'9')
		s=s*10+ch-48,ch=getchar();
	while(ch>='0'&&ch<='9')
		s=s*10+ch-48,ch=getchar();
	return s;
}
void dfs(int x)
{
	for(int i=hd[x];i;i=e[i].nxt)
	{
		if(!~col[e[i].v])
			col[e[i].v]=col[x]^1,dfs(e[i].v);
		else if(col[e[i].v]^1^col[x])
			fl=1;
	}
}
int ok(int x)
{
	memset(hd,e_num=fl=0,sizeof(hd));
	memset(col,-1,sizeof(col));
	for(int i=1;i<=n;i++)
		for(int j=1;j<=3&&j+i<=n;j++)
			if((a[i]^a[i+j])<x)
				add_edge(i,i+j),add_edge(i+j,i);
	for(int i=1;i<=n;i++)
		if(!~col[i])
			col[i]=0,dfs(i);
	return fl^1;
}
int cmp(int x,int y)
{
	return a[x]<a[y];
}
int main()
{
	n=read();
	if(n==2)
		return puts("01"),0;
	for(int i=1;i<=n;i++)
		a[i]=read(),id[i]=i;
	sort(id+1,id+n+1,cmp);
	sort(a+1,a+n+1);
	for(int i=1;i<=n;i++)
		p[id[i]]=i;
	while(l<=r)
	{
		int md=l+r>>1;
		if(ok(md))
			l=md+1;
		else
			r=md-1;
	}
	ok(r);
	for(int i=1;i<=n;i++)
		putchar(col[p[i]]+48);
}

标签:integers,set,XOR,Partition,ch,CF1849F,oplus,字典
From: https://www.cnblogs.com/mekoszc/p/17590369.html

相关文章

  • HDU−4825 XorSum
    01trie树定义:将整数转化为二进制再插入trie树,通常是从高位到低位插入trie。使用场景:寻找与异或相关的结果题目背景:Zeus和Prometheus做了一个游戏,Prometheus给Zeus一个集合,集合中包含了N个正整数,随后Prometheus将向Zeus发起M次询问,每次询问中包含一个正整数S,之后......
  • [ABC308G] Minimum Xor Pair Query 题解
    MinimumXorPairQuery题目大意维护一个序列,支持动态插入,删除,查询最小异或对。思路分析看到查询最小异或对首先想到01Trie,但01Trie不支持删除,考虑暴力套一个线段树分治。需要预处理出每个元素的存活区间,这里使用了map<int,vector<int>>。注意,有的元素会存活到最后,需要特......
  • [ABC308G]MinimumXorPairQuery
    [ABC308G]MinimumXorPairQuery必须知道的性质:对于三个非负整数\(x,y,z(x<y<z)\),有\(\min(x\bigoplusy,y\bigoplusz)<x\bigoplusz\)。证明从二进制最高位开始\(i=\logV\),对\(x,y,z\)进行如下操作:若它们的当前位都两两相同,继续跳到下一位i--。根据......
  • oracle partition by 查询重复记录中的1条数据(获取表去重后的数据所有字段)
    1,partitionby分组后给分组数据排序selectt.*,row_number()over(partitionbyt."name",t."rid"orderbyt."rid")as"sort"from"person"t;2、获取去重后的记录selectt2.*from(SELECTt.*,row_number()over(partitionbyt.&......
  • 【大联盟】20230714 T1 三分网络(tri) 题解 CF1666K 【Kingdom Partition】
    题目描述here。题解赛时得分:\(30/30\),想了很久网络流最后不会。感觉这题就纯纯对脑洞,因为把题目中的\(2\)改成\(3\)就做不了)))不过还是相当有意思的。考虑如下建模方式:首先,考虑最小割。对于每个点\(i\),我们用两个点\(x_{i}\),\(y_i\)来表示。\(x_i\)表示\(i\)号点是......
  • 【大联盟】20230707 xor(xor) CF1456E 【XOR-ranges】
    就我不会*3500/kel题目描述here。题解做法考虑从高位往低位处理,由于有限制的数它的值数确定的,没限制的数值不需要管,因为肯定可以是答案为\(0\)。所以我们考虑区间DP,我们令\(f_{i,l,r,0/1,0/1}\)表示从高往低到第\(i\)位,最左侧\(l\)还有限制,第一个\(0/1\)表示\(x......
  • Codeforces 1456E - XOR-ranges
    考虑一个\(L\lex\leR\)的数\(x\),必然是一段前缀贴着\(L\)或者\(R\),然后下一位脱离了\(L\)和\(R\)的限制,后面随便乱填。注意到一个性质,对于某一位\(d\),考虑这一位上没有限制的那些位置,最优方案肯定是令其等于其左边(或者右边)第一个有限制的数的第\(d\)位上的值。这......
  • AGC034F RNG and XOR
    类似随机游走,令\(f_i\)为第一次操作到\(i\)的期望操作次数,\(p_i\)为每次操作数为\(i\)个概率,显然有:\[f_i=\begin{cases}0&i=0\\1+\sum\limits_{j\;\text{xor}\;k\=\i}p_jf_k&i\neq0\end{cases}\]显然可以高斯消元,不过是\(O(2^{3n})\)的,寄飞。考虑到转移过程中有......
  • CF1083F The Fair Nut and Amusing Xor
    简要题意:给你两个序列\(a,b\),一次操作可以将\(a\)的某一个长度为\(k\)的子区间全部异或上任意值,\(f(a,b)\)为使得\(a\)和\(b\)相同的最少的操作数量。支持单点修改\(a,b\),并在开头和每次修改后输出\(f(a,b)\)的值。\(n,k,q\le2\times10^5,w\le2^{14}\)。题解......
  • CF1603D Artistic Partition
    首先如果\(2^k>n\),答案为\(n\)。否则\(k\le\log_2n\),然后就可以令\(dp_{i,j}\)表示前\(i\)个数分\(j\)段的最小答案。\(dp_{i,j}=\min\limits_{k=1}^{i}\{dp_{k-1,j-1}+c(k,i)\}\)。考虑到:\[\begin{aligned}c(l,r)=&\sum\limits_{i=l}^{r}\sum\limits_{j=l}^......