• 「十二省联考 2019」异或粽子——tire树+堆


    题目

    【题目描述】

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

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

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

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

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

    【输入格式】

    从标准输入读入数据。

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

    接下来一行为 $n$ 个非负整数,第 $i$ 个数为 $a_i$,表示第 $i$ 个粽子的属性值。

    【输出格式】

    输出到标准输出。

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

    【样例输入】

    3 2
    1 2 3

    【样例输出】

    6

    【数据范围与提示】

    |测试点|$n$|$k$|
    |:-:|:-:|:-:|
    |$1sim 8$|$le 10^{3}$|$le 10^{3}$|
    |$9sim 12$|$le 5 imes 10^{5}$|$le 10^{3}$|
    |$13sim 16$|$le 10^{3}$|$le 2 imes 10^{5}$|
    |$17sim 20$|$le 5 imes 10^{5}$|$le 2 imes 10^{5}$|


    对于所有的输入数据都满足:$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$。

    题解

    首先考虑在前缀异或和上暴力,$ n^2 $ 找出所有的值,放进堆里,取前 $ k $ 大的即可,效率 $ O(n^2+log k) $,可以过 $ 60 \% $

    显然把 $ x $ 所有能匹配的都找出来是不可能的,于是考虑在 tire 树上贪心

    建 $ n $ 棵可持久化 tire 树,然后在 $ [0,i-1] $ 上贪心即可

    考虑如何去重

    于是我在测试时想到将 $ x $ 贪心对应的最大值的点 $ p $ 挖掉,然后变成两个区间 $ [l,p-1] $ 和 $ [p+1,r] $,找对应点时建一个链表即可(类似《超级钢琴》)

    然而这样的常数太大,于是 map TLE,但还有 unorder map 嘛,跑得飞快

    其实可以在 tire 树上二分第 $ k $ 大的值,放入堆时记录下是第 $ k $ 大的即可,为什么我没有想到

    代码

    显然二分是不可能去写的

     1 #include<bits/stdc++.h>
     2 #define LL long long
     3 #define U unsigned
     4 #include<tr1/unordered_map>
     5 #define _(d) while(d(isdigit(ch=getchar())))
     6 using namespace std;
     7 LL R(){
     8     LL x;bool f=1;char ch;_(!)if(ch=='-')f=0;x=ch^48;
     9     _()x=(x<<3)+(x<<1)+(ch^48);return f?x:-x;}
    10 const int N=5e5+5;
    11 int n,m,rot[N],tr[N*100][2],cnt,s[N*100][2],nex[N];
    12 LL a[N],sum[N],ans;
    13 struct node{
    14     LL w,v;int l,r;
    15     bool friend operator <(node a,node b){return a.w<b.w;}
    16 };priority_queue<node> q;
    17 tr1::unordered_map<LL,int>mp;
    18 void insert(int &k,int o,LL len,LL v){
    19     if(!~len)return;
    20     k=++cnt;
    21     int f=(v>>len)&1;
    22     tr[k][f^1]=tr[o][f^1],s[k][f^1]=s[o][f^1],s[k][f]=s[o][f]+1;
    23     insert(tr[k][f],tr[o][f],len-1,v);
    24 }
    25 LL query(int k,int o,LL len,LL v){
    26     if(!~len)return 0;
    27     int f=(v>>len)&1;
    28     if(s[k][f^1]-s[o][f^1])
    29         return (1ll<<len)+query(tr[k][f^1],tr[o][f^1],len-1,v);
    30     else return query(tr[k][f],tr[o][f],len-1,v);
    31 }
    32 int find(LL x,int l,int r){
    33     for(int k=mp[x];k;k=nex[k])
    34         if(k<=r&&k>=l)return k;
    35     return 0;}
    36 int main(){
    37     n=R(),m=R();
    38     insert(rot[0],0,32,0);
    39     for(int i=1;i<=n;i++){
    40         a[i]=R(),sum[i]=sum[i-1]^a[i];
    41         nex[i]=mp[sum[i]],mp[sum[i]]=i;
    42         insert(rot[i],rot[i-1],32,sum[i]);
    43     }
    44     for(int i=1;i<=n;i++){
    45         LL w=query(rot[i-1],0,32,sum[i]);
    46         q.push((node){w,sum[i],0,i-1});
    47     }
    48     while(m--){
    49         node now=q.top();q.pop();ans+=now.w;
    50         int id=find(now.w^now.v,now.l,now.r);
    51         if(id-1>=now.l)q.push((node){query(rot[id-1],rot[now.l-1],32,now.v),now.v,now.l,id-1});
    52         if(now.r>=id+1)q.push((node){query(rot[now.r],rot[id+1-1],32,now.v),now.v,id+1,now.r});
    53     }
    54     cout<<ans<<endl;
    55     return 0;
    56 }
    View Code
  • 相关阅读:
    利用朴素贝叶斯算法进行分类-Java代码实现
    机器学习项目中常见的误区
    Chromium项目文化
    又一次定义CDN:为什么是迅雷?
    程序猿的思维修炼
    linux杂谈(十二):CDN加速
    Run-Time Check Failure #2
    打开excel2007&quot;向程序发送命令时出现故障&quot;
    [Unity 3D] Quaternion.LookRotation
    具体解释 IBM Bluemix 端到端开发体验
  • 原文地址:https://www.cnblogs.com/chmwt/p/10667414.html
Copyright © 2020-2023  润新知