这题一开始看的时候一点思路都没有,后来看到题解才想到。其实这题并不难,只是涉及到位运算和字典树罢了。
用a[i]表示前i个数的异或和,那么序列[i,j]的异或和就是a[j] xor a[i-1]。
如果单是枚举i和j的话复杂度到了n^2,肯定会爆,那么就要换一种方法。
问题的关键在对于每个a[j],要于找到i使i到j的异或值最大。
异或最大,感性上认识就是,有差别的位数靠近高位,且越多越好。再看看这个字典树, 如果把26个字母改成0和1的孩子,这样可以形成一个21层的二叉树。从最高位找起,如果有和当前所在的位数相异的位数,就选那条路。 不行,再妥协选相同的位数。
要让这样的做法可行,要插入一个结点选一次(不能选自己之后的结点),且选完课才能把自己插进树里(不能选自己)
代码:
<pre name="code" class="plain">{ ID: ymwbegi1 PROG: cowxor LANG: PASCAL } var n,i,ans,p,q,x,f1,s,a1:longint; f:array[1..21] of longint; a:array[1..600000] of longint; c:array[1..600000] of longint; t,son:array[1..600000,1..2] of longint; procedure count(d,f1:longint); var i:longint; begin if f1=0 then begin s:=t[d,2]; exit; end; for i:=1 to t[d,1] do if c[son[d,i]]<>f[f1] then begin count(son[d,i],f1-1); exit; end; count(son[d,1],f1-1); end; procedure insert(d,f1,x:longint); var i:longint; begin if f1=0 then begin t[d,2]:=x; exit; end; for i:=1 to t[d,1] do if c[son[d,i]]=f[f1] then begin insert(son[d,i],f1-1,x); exit; end; inc(a1); c[a1]:=f[f1]; inc(t[d,1]); son[d,t[d,1]]:=a1; insert(a1,f1-1,x); end; begin assign(input,'cowxor.in'); assign(output,'cowxor.out'); reset(input); rewrite(output); readln(n); for i:=1 to n do begin read(x); if i=1 then a[i]:=x else a[i]:=a[i-1] xor x; end; ans:=-1; a1:=1; for i:=1 to n do begin if a[i]>ans then begin ans:=a[i]; p:=1; q:=i; end; f1:=0; fillchar(f,sizeof(f),0); x:=a[i]; while x>0 do begin inc(f1); f[f1]:=x mod 2; x:=x div 2; end; if i>1 then begin count(1,21); x:=a[s] xor a[i]; if (x>ans)or(x=ans)and(i<q)or(x=ans)and(i=q)and(s+1>p) then begin ans:=x; p:=s+1; q:=i; end; end; insert(1,21,i); end; writeln(ans,' ',p,' ',q); close(input); close(output); end.