[BZOJ2741][FOTILE模拟赛]L-可持久化字典树-分块
2017-12-27 00:46
567 查看
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 ).
其中lastans是上次询问的答案,一开始为0。
Input
第一行两个整数N和M。第二行有N个正整数,其中第i个数为Ai,有多余空格。
后M行每行两个数x,y表示一对询问。
Output
共M行,第i行一个正整数表示第i个询问的结果。Sample Input
3 31 4 3
0 1
0 1
4 3
Sample Output
57
7
HINT
N=12000,M=6000,x,y,Ai在signed longint范围内。Source
By seter虽然每个题解都有写,但是
这题的x+lastans、y+lastans可能会在signed longint范围之外
因为咱一开始没有看见直到心血来潮点开讨论思路:
因为区间很麻烦,所以考虑记录前缀异或和,问题变成在一段区间内,两两数之间的最大异或值。
对于这种最大异或值就要想到trie。
然后因为区间询问,所以trie需要可持久化。
那么得到一个O(nm)的暴力~
考虑优化:分块。
对于每个块,预处理块的起点到块起点后面的每个位置的询问答案。
对于每个询问,首先用最近的块左端点更新答案,然后剩下部分暴力 <
11c72
br>
复杂度O(n√m),可过~
这道题可以给人一个教训:当你实在改不出来时,记得看讨论……
#include<iostream> #include<cmath> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; inline int read() { int x=0;char ch=getchar(); while(ch<'0' || '9'<ch)ch=getchar(); while('0'<=ch && ch<='9')x=x*10+(ch^48),ch=getchar(); return x; } typedef long long ll; const int N=12009; const int M=N*45; const int K=31; int n,m,ans; int a ,s ,sum[119] ; int blk,bel ,fst ; int rt ,ch[M][2],val[M],tot; inline void cp(int x,int y) { val[y]=val[x]; ch[y][0]=ch[x][0]; ch[y][1]=ch[x][1]; } inline int insert(int pre,int dep,int x) { int now=++tot; cp(pre,now); val[now]++; if(!dep)return now; int nxt=(x>>(dep-1))&1; ch[now][nxt]=insert(ch[pre][nxt],dep-1,x); return now; } inline int query(int tl,int tr,int x) { int ret=0; for(int i=K-1;i>=0;i--) { int nxt=(x>>i&1)^1; if(val[ch[nxt]]-val[ch[tl][nxt]]>0) ret|=1<<i,tl=ch[tl][nxt],tr=ch [nxt]; else tl=ch[tl][nxt^1],tr=ch [nxt^1]; } return ret; } int main() { n=read(),m=read(); rt[0]=insert(0,K,s[0]); for(int i=1;i<=n;i++) rt[i]=insert(rt[i-1],K,s[i]=s[i-1]^(a[i]=read())); blk=sqrt(n); fst[bel[1]=0]=1; for(int i=2;i<=n;i++) { bel[i]=i/blk; if(bel[i]!=bel[i-1]) fst[bel[i]]=i; } for(int i=0;fst[i];i++) for(int j=fst[i]+1;j<=n;j++) sum[i][j]=max(sum[i][j-1],query(rt[fst[i]-1],rt[j-1],s[j])); while(m--) { int l=((ll)read()+(ll)ans)%(ll)n+1; int r=((ll)read()+(ll)ans)%(ll)n+1; if(l>r)swap(l,r); int p=l/blk+1; ans=sum[p][r]; for(int i=min(p*blk-1,r-1);i>=l-1;i--) ans=max(ans,query(rt[i],rt[r],s[i])); printf("%d\n",ans); } return 0; } 相关文章推荐
- bzoj 2741 【FOTILE模拟赛】L 可持久化字典树+分块
- 【BZOJ2741】【FOTILE模拟赛】L 可持久化字典树+分块
- [可持久化字典树 分块] BZOJ 2741 【FOTILE模拟赛】L
- bzoj 2741: 【FOTILE模拟赛】L (分块+可持久化trie树)
- 【bzoj2741】[FOTILE模拟赛]L 可持久化Trie树+分块
- [BZOJ]2741: 【FOTILE模拟赛】L 可持久化Trie+分块
- [BZOJ2741][[FOTILE模拟赛]][可持久化Trie+分块]
- 【分块】【可持久化Trie】bzoj2741 【FOTILE模拟赛】L
- BZOJ 2741 【FOTILE模拟赛】L 分块+可持久化Trie树
- BZOJ 2741 【FOTILE模拟赛】L 可持久化Trie 分块
- BZOJ 2741【FOTILE模拟赛】L 分块+可持久化Trie树
- [BZOJ2741]【FOTILE模拟赛】L(分块+可持久化trie树)
- 【BZOJ2741】【FOTILE模拟赛】L 分块+可持久化Trie树
- BZOJ 2741: 【FOTILE模拟赛】L [分块 可持久化Trie]
- bzoj 2741 【FOTILE模拟赛】L 分块 可持久化trie树
- BZOJ2741 【FOTILE模拟赛】L 可持久化Trie+分块
- bzoj2741: 【FOTILE模拟赛】L【可持久化trie树+分块】
- bzoj2741 FOTILE模拟赛L 可持久化Trie
- BZOJ - 2741: 【FOTILE模拟赛】L 分块+可持久化数据结构
- BZOJ 2741 【FOTILE模拟赛】L(可持久化trie)