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

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

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

题目描述

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

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

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

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

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

输入格式

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

接下来一行为 n 个非负整数,第 i 个数为 ai,表示第 i 个粽子的属性值。
对于所有的输入数据都满足:1n5×105, 1kmin{n(n1)2,2×105}, 0ai4294967295

输出格式

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

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

我们用依旧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 @   liuboom  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示