异或粽子

异或粽子

小粽是一个喜欢吃粽子的好孩子。今天她在家里本身作起了粽子。node

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

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

小粽想品尝不一样口味的粽子,所以它不但愿用一样的馅儿的集合作出一个以上的粽子。spa

小粽但愿她作出的全部粽子的美味度之和最大。请你帮她求出这个值吧!code


Solblog

前缀和完后至关于求两点xor和的前k大。ci

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

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

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

而后查第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\n",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
相关文章
相关标签/搜索