異或糉子

異或糉子

小糉是一個喜歡吃糉子的好孩子。今天她在家裏本身作起了糉子。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
相關文章
相關標籤/搜索