zoukankan      html  css  js  c++  java
  • [loj3048]异或粽子

    先对其求出前缀异或和,然后$o(k)$次枚举,每次选择最大值,考虑如何维护
    可以全局开一个堆,维护出每一个点的最大值的最大值,那么相当于要在一个点中删去一个点再找到最大值
    将这些删去的点重新建成一颗trie树,与所有数构成的trie树减一下,就可以找到新的最大值了,再用堆维护即可
    有一些细节:1.数值范围较大,需要开long long;2.由于无法判断位置关系,因此要取2k个并将答案除以2

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 500005
     4 #define ll long long
     5 set<pair<ll,int> >s;
     6 int V,n,m,ch[N*70][2],sz[N*70];
     7 ll ans,a[N];
     8 void add(int k,ll x){
     9     sz[k]++;
    10     for(int i=31;i>=0;i--){
    11         int p=((((1LL<<i)&x)>0));
    12         if (!ch[k][p])ch[k][p]=++V;
    13         k=ch[k][p];
    14         sz[k]++;
    15     }
    16 }
    17 ll query(int k1,int k2,ll x){
    18     ll ans=0;
    19     for(int i=31;i>=0;i--){
    20         int p=(((1LL<<i)&x)==0);
    21         if (sz[ch[k1][p]]==sz[ch[k2][p]])p^=1;
    22         ans+=p*(1LL<<i);
    23         k1=ch[k1][p];
    24         k2=ch[k2][p];
    25     }
    26     return ans;
    27 }
    28 int main(){
    29     scanf("%d%d",&n,&m);
    30     for(int i=1;i<=n;i++){
    31         scanf("%lld",&a[i]);
    32         a[i]^=a[i-1];
    33     }
    34     V=n+2;
    35     for(int i=0;i<=n;i++)add(1,a[i]);
    36     for(int i=0;i<=n;i++)s.insert(make_pair(-(a[i]^query(1,i+2,a[i])),i));
    37     m*=2;
    38     for(int i=1;i<=m;i++){
    39         ans-=(*s.begin()).first;
    40         int k=(*s.begin()).second;
    41         s.erase(s.begin());
    42         add(k+2,query(1,k+2,a[k]));
    43         s.insert(make_pair(-(a[k]^query(1,k+2,a[k])),k));
    44     }
    45     printf("%lld",ans/2);
    46 } 
    View Code
  • 相关阅读:
    比较相同一个表中两个字段值
    thinkphp在原字段上面进行加减操作
    前端页面中语音提示
    LeetCode 47——全排列 II
    剑指 Offer——最小的 K 个数
    LeetCode 46——全排列
    LeetCode 103——二叉树的锯齿形层次遍历
    剑指 Offer——数组中的逆序对
    二维数组和指针
    Non-local Neural Networks
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/12577286.html
Copyright © 2011-2022 走看看