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,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.

时间: 2024-11-05 00:09:34

bzoj2741: 【FOTILE模拟赛】L的相关文章

BZOJ2741[FOTILE模拟赛]L

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).

【BZOJ2741】【块状链表+可持久化trie】FOTILE模拟赛L

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+last

【BZOJ】【2741】【FOTILE模拟赛】L

可持久化Trie+分块 神题……Orz zyf & lyd 首先我们先将整个序列搞个前缀异或和,那么某一段的异或和,就变成了两个数的异或和,所以我们就将询问[某个区间中最大的区间异或和]改变成[某个区间中 max(两个数的异或和)] 要是我们能将所有[l,r]的答案都预处理出来,那么我们就可以O(1)回答了:然而我们并不能. 一个常见的折中方案:分块! 这里先假设我们实现了一个神奇的函数ask(l,r,x),可以帮我们求出[l,r]这个区间中的数,与x最大的异或值. 我们不预处理所有的左端点,我

bzoj 2741: 【FOTILE模拟赛】L 分塊+可持久化trie

2741: [FOTILE模拟赛]L Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 1116  Solved: 292[Submit][Status] Description FOTILE得到了一个长为N的序列A,为了拯救地球,他希望知道某些区间内的最大的连续XOR和. 即对于一个询问,你需要求出max(Ai xor Ai+1 xor Ai+2 ... xor Aj),其中l<=i<=j<=r. 为了体现在线操作,对于一个询问(x,y):

bzoj2741【FOTILE模拟赛】L

http://www.lydsy.com/JudgeOnline/problem.php?id=2741 分块或可持久化trie 可以先看看这个:高斯消元解XOR方程组 分块做法: 我们先求出前i个数的异或和,即b[i]=a[1]^a[2]^...^a[i],不失一般性,记b[0]=0. 那么a[i]^a[i+1]^...^a[j-1]^a[j]=b[j]^b[i-1]. 所以原问题变成在b[l-1...r]中任选2个数,使得异或和最大. 我们将0..N分成$\sqrt{N}$块,不妨记第i块的

【BZOJ2741】【FOTILE模拟赛】L 可持久化字典树+分块

广告: #include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/44496739"); } 题解: 首先我们处理出来sum[0,n]作为异或前缀和,然后答案就不再是[l,r]中间某段区间的异或和,而转化成求了[l?1,r]中任意两点异或和的最大值. 然后我们分块处理出fi,j表示 [第i块的开头,j

【分块】【可持久化Trie】bzoj2741 【FOTILE模拟赛】L

类似p3261,只是我们需要分块预处理anss[i][j]第i块到第j块的答案,然后整块的部分直接获得,零散的部分暴力. #include<cstdio> #include<algorithm> #include<cmath> using namespace std; #define N 12001 #define MAXBIT 31 #define BN 115 int root[N],ch[N*(MAXBIT+1)][2],sz[N*(MAXBIT+1)],tot;

BZOJ 2741【FOTILE模拟赛】L 分块+可持久化Trie树

题目大意 给出一个序列,求[l, r]中的最大连续xor 和. 强制在线 思路 先把整个序列分成n  √  块,预处理每一块的开头到每个数字的最大连续xor 和.这个我们只需处理出前缀xor 和,之后用可持久化Trie树就可以搞定.这样询问的右边就是整块的了.剩下左边的随便暴力一下就能过了.. CODE #define _CRT_SECURE_NO_WARNINGS #include <cmath> #include <cstdio> #include <cstring>

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

题意: 区间内最大连续异或和 5点调试到现在....人生无望 但总算A掉了 一开始想错可持久化trie的作用了...可持久化trie可以求一个数与一个数集的最大异或和 做法比较明显,前缀和后变成选区间内两个元素异或最大 考虑分块,预处理$f[i][j]$第i块到第j块选两个元素异或最大 询问时两边用可持久化trie暴力,中间整块已经预处理了 可以发现预处理复杂度$O(N\sqrt{N}*30)$,必须要枚举块中元素来算,不如直接保存下来$f[i][j]$为第i块到第j个元素的答案 如果说有什么教