「LOJ#10051」「一本通 2.3 例 3」Nikitosh 和異或 「LOJ#10050」「一本通 2.3 例 2」The XOR Largest Pair(Trie
阿新 • • 發佈:2018-11-09
題目描述
原題來自:CODECHEF September Challenge 2015 REBXOR
1≤r1<l2≤r2≤N,x⨁yx\bigoplus yx⨁y 表示 xxx 和 yyy 的按位異或。
輸入格式
輸出格式
輸出一行包含給定表示式可能的最大值。
樣例
資料範圍與提示
5,0≤Ai≤109。
題解
首先記錄異或字首和$s[i]=a[1]⨁a[2]⨁a[3]...⨁a[i]$。
設$l[i]$為以$i$結尾的區間中,異或值的最大值。
因為異或有$x⨁x=0$的性質,所以區間$[l,r]$的異或值
$=a[l]⨁a[l+1]⨁...⨁a[r]$
$=(a[1]⨁a[2]⨁a[3]...⨁a[l-1])⨁(a[1]⨁a[2]⨁a[3]⨁...a[r])$
$=s[l-1]⨁s[r]$,
所以求$l[i]$,轉化為找$j<i$,使得$s[j]⨁s[i]$最大。
轉化為「LOJ#10050」「一本通 2.3 例 2」The XOR Largest Pair(Trie
以相似的方法可以求出$r[i]$(以$i$開頭的區間中,異或值的最大值)。
在實際操作的過程中可以$l[i]=max(l[i-1],find(x))$,這樣$ans=max(l[i]+r[i+1])$就行了。
書上的操作是直接$l[i]=find(x)$然後$ans=max(l[i]+r[i+1])$,感覺不能理解qwq
1 編號 題目 狀態 分數 總時間 記憶體 程式碼 / 答案檔案 提交者 提交時間 2 #237651 #10051. 「一本通 2.3 例 3」Nikitosh 和異或 Accepted 1002765 ms 43900 KiB C++ / 1.2 K qwerta 2018-10-20 17:15:56 3 4 #include<iostream> 5 #include<cstring> 6 #include<cstdio> 7 #include<cmath> 8 using namespace std; 9 int s[400003]; 10 int l[400003]; 11 int r[400003]; 12 struct emm{ 13 int nxt[2]; 14 }a[12800003]; 15 int cnt=0; 16 int b[33]; 17 void add(int x) 18 { 19 int j=-1; 20 memset(b,0,sizeof(b)); 21 while(x) 22 { 23 b[++j]=x&1; 24 x>>=1; 25 } 26 int k=0; 27 for(int j=32;j>=0;--j) 28 { 29 if(!a[k].nxt[b[j]]) 30 a[k].nxt[b[j]]=++cnt; 31 k=a[k].nxt[b[j]]; 32 } 33 return; 34 } 35 int find(int x) 36 { 37 int now=0,k=0; 38 for(int j=32;j>=0;--j) 39 { 40 if(a[k].nxt[1-b[j]]) 41 { 42 now+=(1<<j); 43 k=a[k].nxt[1-b[j]]; 44 } 45 else k=a[k].nxt[b[j]]; 46 } 47 return now; 48 } 49 int main() 50 { 51 //freopen("a.in","r",stdin); 52 int n; 53 scanf("%d",&n); 54 for(int i=1;i<=n;++i) 55 scanf("%d",&s[i]); 56 int x=0; 57 for(int i=1;i<=n;++i) 58 { 59 x^=s[i];//這裡的x為字首和 60 add(x); 61 l[i]=max(l[i-1],find(x)); 62 } 63 //重做一次找r[i] 64 memset(a,0,cnt+1); 65 x=0,cnt=0; 66 for(int i=n;i;--i) 67 { 68 x^=s[i]; 69 add(x); 70 r[i]=max(r[i+1],find(x)); 71 } 72 int ans=0; 73 for(int i=1;i<n;++i) 74 ans=max(ans,l[i]+r[i+1]); 75 cout<<ans; 76 return 0; 77 }