#4349. 「十二省联考 2019」异或粽子

题意

内存限制:1024 MiB
时间限制:1500 ms
小粽是一个喜欢吃粽子的好孩子。今天她在家里自己做起了粽子。

小粽面前有 n n n 种互不相同的粽子馅儿,小粽将它们摆放为了一排,并从左至右编号为 1 1 1 n n n。第 i i i 种馅儿具有一个非负整数的属性值 a i a_i ai。每种馅儿的数量都足够多,即小粽不会因为缺少原料而做不出想要的粽子。小粽准备用这些馅儿来做出 k k k 个粽子。

小粽的做法是:选两个整数数 l , r l,r l,r,满足 1 ≤ l ≤ r ≤ n 1\le l\le r\le n 1lrn,将编号在 [ l , r ] [l,r] [l,r] 范围内的所有馅儿混合做成一个粽子,所得的粽子的美味度为这些粽子的属性值的异或和。(异或就是我们常说的 x o r \mathrm{xor} xor 运算,即 C/C++ 中的 ^ 运算符或 Pascal 中的 xor 运算符)

小粽想品尝不同口味的粽子,因此它不希望用同样的馅儿的集合做出一个以上的粽子。

小粽希望她做出的所有粽子的美味度之和最大。请你帮她求出这个值吧!

1 ≤ n ≤ 5 × 1 0 5 , 1 ≤ k ≤ min ⁡ { n ( n − 1 ) 2 , 2 × 1 0 5 } , 0 ≤ a i ≤ 4 , 294 , 967 , 295 1\le n \le 5 \times 10^{5},1\le k\le \min\left\{\frac{n(n-1)}{2},2 \times 10^{5}\right\},0\le a_i \le 4,294,967,295 1n5×105,1kmin{2n(n1),2×105},0ai4,294,967,295

题解

a i a_i ai 变成前缀异或和,所以实际上是在 [ 0 , n ] [0,n] [0,n] 中选 k k k ( x , y ) (x,y) (x,y) 使 ∑ a x ⊕ a y \sum a_x \oplus a_y axay 最大

考虑到 k k k 不是很大,我们可以建立堆,一开始把每个数选到最大的数丢到堆中,然后以异或值作为关键字排序,每次取出堆顶,然后找其第二大异或值丢到堆中……

所以可以发现我们需要查询对于 i i i j ∈ [ 0 , i − 1 ] j \in [0,i-1] j[0,i1] a i ⊕ a j a_i \oplus a_j aiaj k k k 大数是多少

所以可以建立可持久化 t r i e trie trie 树,在 t r i e trie trie 树上进行二分即可

#include 
#define I inline
#define LL long long
using namespace std;
const int N=5e5+5;
int n,K,T[N],tt;LL a[N],ans;
struct O{int s,ch[2];}t[N<<6];
struct Q{
	int x,k;LL v;
	I friend bool operator < (const Q& A,const Q& B){
		return A.vq;
I void ins(int& x,LL v,int d){
	t[++tt]=t[x];x=tt;t[x].s++;
	if (~d) ins(t[x].ch[(v>>d)&1ll],v,d-1);
}
I LL query(int x,LL y,int k,int d){
	if (!~d) return 0;
	bool v=(y>>d)&1ll;
	int s=t[t[x].ch[v^1]].s;
	if (k<=s) return query(t[x].ch[v^1],y,k,d-1)|(1ll<

你可能感兴趣的:(#4349. 「十二省联考 2019」异或粽子)