• 异或粽子


    异或粽子

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

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

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

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

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


    Sol

    前缀和完后相当于求两点xor和的前k大。

    有一个很好的想法:考虑左端点,先把和这个左端点xor最大的右端点放进堆里,然后每次取堆顶,并接着把次大的放进去。

    也就是后面的答案一定会由前面的答案得来。

    以后想这种区间问题,可以多从端点的角度考虑问题,固定一个端点,另一个统计,取最大等等。

    然后查第k大就可持久化trie实现。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<cmath>
     7 #include<queue>
     8 #define maxn 500005
     9 #define ll long long
    10 using namespace std;
    11 int n,K,cnt,rt[maxn];
    12 ll a[maxn],ans;
    13 struct node{
    14     int ch[2],sz;
    15 }tr[maxn*42];
    16 struct no{
    17     int x,kth;ll v;
    18 };
    19 bool operator <(no a,no b){
    20     return a.v<b.v;
    21 }
    22 priority_queue<no>q;
    23 int get(int w,ll v){
    24     return ((1LL<<w)&v)>0;
    25 }
    26 void ins(int w,int &k,int la,ll v){
    27     if(!k)k=++cnt;
    28     if(w<0){
    29         tr[k].sz=tr[la].sz+1;return;
    30     }
    31     int f=get(w,v);
    32     ins(w-1,tr[k].ch[f],tr[la].ch[f],v);
    33     tr[k].ch[f^1]=tr[la].ch[f^1];
    34     tr[k].sz=tr[tr[k].ch[0]].sz+tr[tr[k].ch[1]].sz;
    35 }
    36 ll ask(int w,int k,int la,ll v,int kth){
    37     if(w<0)return 0;
    38     int f=get(w,v);
    39     int s=tr[tr[k].ch[f^1]].sz-tr[tr[la].ch[f^1]].sz;
    40     if(w<=5){
    41         //printf("%d %d v=%d Kth=%d s=%d
    ",w,k,v,kth,s);
    42     }
    43     if(s>=kth)return ask(w-1,tr[k].ch[f^1],tr[la].ch[f^1],v,kth)+(1LL<<w);
    44     else return ask(w-1,tr[k].ch[f],tr[la].ch[f],v,kth-s);
    45 }
    46 int main(){
    47     cin>>n>>K;
    48     ins(31,rt[0],rt[0],0);
    49     for(int i=1;i<=n;i++){
    50         scanf("%lld",&a[i]);
    51         a[i]^=a[i-1];
    52         ins(31,rt[i],rt[i-1],a[i]);
    53     }
    54     for(int i=0;i<=n;i++){
    55         no t;t.kth=1;t.x=i;t.v=ask(31,rt[n],rt[i],a[t.x],1);
    56         //cout<<t.x<<' '<<t.v<<endl;
    57         q.push(t);
    58     }int co=0;
    59     while(!q.empty()){
    60         no t=q.top();q.pop();
    61         ans+=t.v;t.v=ask(31,rt[n],rt[t.x],a[t.x],t.kth+1);t.kth++;
    62         co++;if(co==K)break;
    63         q.push(t);
    64     }
    65     cout<<ans<<endl;
    66     return 0;
    67 }
    View Code
  • 相关阅读:
    Objective-C马路成魔【14-关键C语言功能】
    js正则表达式语法
    Python 得到Twitter所有用户friends和followers
    error:stray&#39;243&#39;in program
    VC各种方法获得的窗口句柄
    新东方雅思词汇---5.2
    php中this,self,parent三个关键字的区别辨析
    英语影视台词---一、少年派的奇幻漂流
    英语常用单词分类---1
    amazeui的表单开关插件的自定义事件必须添加.bootstrapSwitch 命名空间,给了我们什么启示
  • 原文地址:https://www.cnblogs.com/liankewei/p/10668372.html
Copyright © 2020-2023  润新知