[Trie][贪心][堆] LibreOJ #3048 异或粽子

题目描述

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

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

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

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

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

输入输出格式

输入格式:

 

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

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

 

输出格式:

 

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

 

输入输出样例

输入样例#1: 
3 2
1 2 3
输出样例#1: 
6

 

题解

  • 把前缀和扔进Trie里面,用一个堆维护每个位置当前的最大贡献,每次贪心取然后更改

代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <queue>
 5 #define ll long long
 6 using namespace std;
 7 const ll N=500010,M=N*32;
 8 struct node 
 9 {
10     ll id,val;
11     bool operator <(const node &o)const { return val<o.val; }
12 };
13 priority_queue<node> Q;
14 ll n,k,tot,ans,now[N],ch[M][2],sz[M],cnt[M],s[N];
15 void insert(ll x)
16 {
17     ll r=0;
18     for (ll i=31,c;~i;i--)
19     {
20         c=(x&(1ll<<i))?1:0;
21         if (!ch[r][c]) ch[r][c]=++tot;
22         ++sz[r=ch[r][c]];
23     }
24     ++cnt[r];
25 }
26 ll kth(ll x,ll k) 
27 {
28     ll r=0; ll R=0;
29     for (ll i=31,c;~i;i--) 
30     {
31         c=(x&(1ll<<i))?0:1;
32         if (sz[ch[r][c]]<k) k-=sz[ch[r][c]],r=ch[r][!c]; else R^=1ll<<i,r=ch[r][c];
33     }
34     return R;
35 }
36 int main()
37 {    
38     scanf("%lld%lld",&n,&k),k<<=1,insert(0);
39     for (ll i=1,x;i<=n;i++) scanf("%lld",&x),s[i]=s[i-1]^x,insert(s[i]);
40     for (ll i=0;i<=n;i++) Q.push(node{i,kth(s[i],++now[i])});
41     while (k--)
42     {
43         node u=Q.top(); Q.pop();
44         if (k&1) ans+=u.val;
45         if (now[u.id]<n) Q.push(node{u.id,kth(s[u.id],++now[u.id])});
46     }
47     printf("%lld",ans);
48 }

 

 

posted @ 2019-07-16 11:37  BEYang_Z  阅读(211)  评论(0编辑  收藏  举报