[loj3048]异或粽子

Posted pywbktda

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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

 

以上是关于[loj3048]异或粽子的主要内容,如果未能解决你的问题,请参考以下文章

#4349. 「十二省联考 2019」异或粽子

[十二省联考2019]异或粽子(可持久化tire,堆)

P5283 [十二省联考2019]异或粽子

P5283 [十二省联考2019]异或粽子 可持久化01Trie+线段树

[十二省联考]异或粽子

P5283 [十二省联考2019]异或粽子