zoukankan      html  css  js  c++  java
  • #4349. 「十二省联考 2019」异或粽子

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

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

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

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

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

    $1le n le 5 imes 10^{5},1le kle minleft{frac{n(n-1)}{2},2 imes 10^{5} ight},0le a_i le 4,294,967,295$
    题解

    把 $a_i$ 变成前缀异或和,所以实际上是在 $[0,n]$ 中选 $k$ 对 $(x,y)$ 使 $sum a_x oplus a_y$ 最大

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

    所以可以发现我们需要查询对于 $i$ , $j in [0,i-1]$ 的 $a_i oplus a_j$ 第 $k$ 大数是多少

    所以可以建立可持久化 $trie$ 树,在 $trie$ 树上进行二分即可

    代码

    #include <bits/stdc++.h>
    #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.v<B.v;
        }
    };priority_queue<Q>q;
    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<<d);
        return query(t[x].ch[v],y,k-s,d-1);
    }
    int main(){
        scanf("%d%d",&n,&K);
        for (int i=1;i<=n;i++)
            scanf("%lld",&a[i]),a[i]^=a[i-1],
            ins(T[i]=T[i-1],a[i-1],31),
            q.push((Q){i,1,query(T[i],a[i],1,31)});
        for (int i=1;i<=K;i++){
            Q y=q.top();q.pop();ans+=y.v;
            if (y.k<=y.x) q.push((Q){y.x,y.k+1,query(T[y.x],a[y.x],y.k+1,31)});
        }
        return printf("%lld
    ",ans),0;
    }
  • 相关阅读:
    【Oracle/PLSQL】没事玩一个简单的表充值程序
    findmnt命令查找已挂载的文件系统
    如何让shell脚本变成可执行文件
    在Linux中如何查看文件的修改日期
    Dutree – Linux上的命令行磁盘使用情况分析工具
    用FRP做内网穿透使用远程桌面连接家里的windows电脑
    Dog-用于DNS查询的命令行工具
    【DeFi】一文读懂预言机原理、类型、现状和发展方向
    Vitalik Buterin 解读 Nathan Schneider 论文:加密经济治理的局限与改进思路
    Vitalik:回顾区块链近 5 年经济学进展,以及新出现的问题
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/10667280.html
Copyright © 2011-2022 走看看