• [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 imes 10^51n5×105, 1 leqslant k leqslant minleft{frac{n(n-1)}{2},2 imes 10^{5} ight}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 }

     

  • 相关阅读:
    VB6SP6极度精简兼容绿色版
    Upnp资料整理
    RevMan简单入门指南
    小程序 --flex
    IV
    2017-10-27错误日志
    170616_2
    170616
    2017-06-07
    111111112222
  • 原文地址:https://www.cnblogs.com/Comfortable/p/11193864.html
Copyright © 2020-2023  润新知