bzoj2741: FOTILE模拟赛L

Posted OldJang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj2741: FOTILE模拟赛L相关的知识,希望对你有一定的参考价值。

2741: 【FOTILE模拟赛】L

Time Limit: 15 Sec  Memory Limit: 162 MB
Submit: 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 ).
其中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


Sample Output

5
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.
View Code

 

 

 

以上是关于bzoj2741: FOTILE模拟赛L的主要内容,如果未能解决你的问题,请参考以下文章

bzoj2741: FOTILE模拟赛L

BZOJ2741[FOTILE模拟赛]L

BZOJ2741 FOTILE模拟赛L 可持续化trie + 分块

BZOJ 2741 FOTILE模拟赛L(可持久化trie)

BZOJ 2741: FOTILE模拟赛L [分块 可持久化Trie]

CH 4913 Fotile模拟赛L (可持久化trie std)