bzoj2741: FOTILE模拟赛L
Posted OldJang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj2741: FOTILE模拟赛L相关的知识,希望对你有一定的参考价值。
2741: 【FOTILE模拟赛】L
Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 2679 Solved: 766
[Submit][Status][Discuss]
Description
FOTILE得到了一个长为N的序列A,为了拯救地球,他希望知道某些区间内的最大的连续XOR和。
即对于一个询问,你需要求出max(Ai xor Ai+1 xor Ai+2 ... xor Aj),其中l<=i<=j<=r。
为了体现在线操作,对于一个询问(x,y):
l = min ( ((x+lastans) mod N)+1 , ((y+lastans) mod N)+1 ).
r = max ( ((x+lastans) mod N)+1 , ((y+lastans) mod N)+1 ).
r = max ( ((x+lastans) mod N)+1 , ((y+lastans) mod N)+1 ).
其中lastans是上次询问的答案,一开始为0。
Input
第一行两个整数N和M。
第二行有N个正整数,其中第i个数为Ai,有多余空格。
后M行每行两个数x,y表示一对询问。
Output
共M行,第i行一个正整数表示第i个询问的结果。
Sample Input
3 3
1 4 3
0 1
0 1
4 3
1 4 3
0 1
0 1
4 3
Sample Output
5
7
7
7
7
HINT
HINT
N=12000,M=6000,x,y,Ai在signed longint范围内。
题解
首先很显然的转换是先求下前缀和sum,然后求某个区间内两个数xor最大是多少。
对于xor的东西我们经常用到可持久化trie,考虑暴力就是直接枚举每个数然后在[l,r]的trie上走一下就出来了。这样我们可以分块来预处理。首先求出f[i,j]表示第j个数和第i块里的数所能产生的最大xor和,然后可以很方便的处理出从第i块的第一个数到整个序列中的第j个数与第i块中的数产生的最大价值(为了方便还是用f[i,j]表示)。
之后对于每个询问我们看一下每个完整的块的f[i,r],再对两端多出来的部分在可持久化trie上走一遍就行了
1 program j01; 2 const maxn=12086; 3 var f:array[0..2000,0..maxn]of longint; 4 t:array[0..maxn*100]of record son:array[0..1]of longint; sum:longint; end; 5 sum,root,l,r,bel:array[0..maxn]of longint; 6 bin:array[0..30]of longint; 7 a,n,m,i,tt,size,cnt,j,now,ll,rr:longint; 8 x,y,ans:int64; 9 10 function max(a,b:int64):int64; 11 begin 12 if a>b then exit(a) else exit(b); 13 end; 14 15 function min(a,b:int64):int64; 16 begin 17 if a<b then exit(a) else exit(b); 18 end; 19 20 procedure insert(id:longint); 21 var nowx,nowy,i,dd:longint; 22 begin 23 nowx:=root[id-1];inc(tt);root[id]:=tt;nowy:=tt; 24 for i:=30 downto 0 do 25 begin 26 t[nowy]:=t[nowx];inc(t[nowy].sum); 27 dd:=ord(sum[id] and bin[i]>0); 28 inc(tt);t[nowy].son[dd]:=tt; 29 nowx:=t[nowx].son[dd];nowy:=t[nowy].son[dd]; 30 end; 31 t[nowy]:=t[nowx];inc(t[nowy].sum); 32 end; 33 34 function ask(v,rl,rr:longint):longint; 35 var tmp,i,dd,d2:longint; 36 begin 37 tmp:=0; 38 for i:=30 downto 0 do 39 begin 40 dd:=1-ord(v and bin[i]>0); 41 if t[t[rr].son[dd]].sum-t[t[rl].son[dd]].sum>0 then 42 tmp:=tmp+bin[i] else dd:=1-dd; 43 rl:=t[rl].son[dd];rr:=t[rr].son[dd]; 44 end; 45 exit(tmp); 46 end; 47 48 function query(x,y:longint):longint; 49 var tmp,i:longint; 50 begin 51 tmp:=0; 52 for i:=bel[x]+1 to bel[y]-1 do tmp:=max(tmp,f[i,y]); 53 for i:=x to min(y,r[bel[x]]) do tmp:=max(tmp,ask(sum[i],root[x-1],root[y])); 54 for i:=max(l[bel[y]],x) to y do tmp:=max(tmp,ask(sum[i],root[x-1],root[y])); 55 exit(tmp); 56 end; 57 58 begin 59 readln(n,m); 60 bin[0]:=1; 61 for i:=1 to 30 do bin[i]:=bin[i-1] shl 1; 62 for i:=2 to n+1 do 63 begin 64 read(a);sum[i]:=sum[i-1] xor a; 65 end; 66 for i:=1 to n+1 do insert(i); 67 inc(n); 68 size:=trunc(sqrt(n)); 69 ans:=0; 70 for i:=1 to n do bel[i]:=(i-1) div size+1; 71 cnt:=bel[n]; 72 for i:=1 to cnt do 73 begin 74 l[i]:=(i-1)*size+1; 75 if i<>cnt then r[i]:=i*size else r[i]:=n; 76 end; 77 for i:=1 to cnt do 78 for j:=l[i] to n do 79 f[i,j]:=ask(sum[j],root[l[i]-1],root[r[i]]); 80 for i:=1 to cnt do 81 for j:=l[i]+1 to n do f[i,j]:=max(f[i,j],f[i,j-1]); 82 dec(n); 83 for i:=1 to m do 84 begin 85 readln(x,y); 86 x:=x mod n;y:=y mod n;ans:=ans mod n; 87 ll:=min((x+ans)mod n+1,(y+ans)mod n+1);rr:=max((x+ans)mod n+1,(y+ans)mod n+1)+1; 88 ans:=query(ll,rr); 89 writeln(ans); 90 end; 91 end.
以上是关于bzoj2741: FOTILE模拟赛L的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ2741 FOTILE模拟赛L 可持续化trie + 分块
BZOJ 2741 FOTILE模拟赛L(可持久化trie)