P5283 [十二省联考 2019] 异或粽子

P5283 [十二省联考 2019] 异或粽子

[十二省联考 2019] 异或粽子

题目描述

小粽是一个喜欢吃粽子的好孩子。今天她在家里自己做起了粽子。

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

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

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

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

输入格式

第一行两个正整数 \(n\), \(k\),表示馅儿的数量,以及小粽打算做出的粽子的数量。

接下来一行为 \(n\) 个非负整数,第 \(i\) 个数为 \(a_i\),表示第 \(i\) 个粽子的属性值。
对于所有的输入数据都满足:\(1 \leqslant n \leqslant 5 \times 10^5\), \(1 \leqslant k \leqslant \min\left\{\frac{n(n-1)}{2},2 \times 10^{5}\right\}\), \(0 \leqslant a_i \leqslant 4 294 967 295\)

输出格式

输出一行一个整数,表示小粽可以做出的粽子的美味度之和的最大值。

----------------------------------------------------------------------------------

我们用依旧0/1Trie 维护粽子馅的xor前缀和

由题目可知:

小粽面前有n种互不相同的粽子馅儿

它不希望用同样的馅儿的集合做出一个以上的粽子

也就是说,我们只需要保证同样的 [l,r] 不会重复出现就好了

不难想到开一个优先队列来维护,每次在 [l,r]
[pos,r] 做出一个粽子之后,将其拆分为 [l,pos-1][pos+1,r] 就好了

Code:

#include<bits/stdc++.h>
const int N=5e5+5;
typedef long long ll;
using namespace std;
int n,k,tot;
ll a[N];
int rt[N];
ll ans;
struct Trie{
	int ch[2],cnt,id;
}t[N*40];
void ins(int &now,int last,int len,int id,int x)
{
	now=++tot;
	t[now]=t[last];
	t[now].cnt++;
	if(len==-1)
	{
		t[now].id=id;
		return ;
	}
	int bit=(x>>len)&1;
	ins(t[now].ch[bit],t[last].ch[bit],len-1,id,x);
}
int find_id(int l,int r,int len,int x)
{
	if(len==-1)return t[r].id;
	int bit=(x>>len)&1;
	if(t[t[l].ch[bit^1]].cnt<t[t[r].ch[bit^1]].cnt)
	{
		return find_id(t[l].ch[bit^1],t[r].ch[bit^1],len-1,x);
	}
	else 
	{
		return find_id(t[l].ch[bit],t[r].ch[bit],len-1,x);
	}
}
struct Range
{
	int l,r,x,id;
	ll val;
	Range(int _l=0,int _r=0,int _x=0)
	{
		l=_l,r=_r,x=_x;
		id=find_id(rt[l-1],rt[r],31,a[x]);
		val=a[x]^a[id-1];
		//cout<<"id:"<<l<<" "<<r<<" "<<x<<"=="<<id<<":"<<val<<"\n";
	}
	bool operator <(const Range &r1)const{
		return val<r1.val;
	}
}; 
priority_queue<Range> Q;
void work()
{
	cin>>n>>k;
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&a[i]);
		a[i]^=a[i-1];
	}
	for(int i=1;i<=n;i++)
	{
		rt[i]=rt[i-1];
		ins(rt[i],rt[i],31,i,a[i-1]);
	}
	for(int i=1;i<=n;i++)
	{
		Q.push(Range(1,i,i));
	}
	for(int i=1;i<=k;i++)
	{
		Range tp=Q.top();Q.pop();
		int l=tp.l,r=tp.r,id=tp.id,x=tp.x;
		ll val=tp.val;
		ans+=val;
		//cout<<"ans:"<<val<<"--"<<l<<" "<<id<<" "<<r<<"\n";
		if(l<=id-1) Q.push(Range(l,id-1,x));
		if(id+1<=r) Q.push(Range(id+1,r,x));
	}
	printf("%lld",ans);
}
int main()
{
	freopen("P5283.in","r",stdin);//freopen("P5283.out","w",stdout);
	work();
}
posted @ 2024-12-06 11:43  liuboom  阅读(40)  评论(0)    收藏  举报