You are given a sequence A[1], A[2], ..., A[N]. (0 ≤ A[i] < 231, 1 ≤ N ≤ 12000).

A query is defined as follows:

  • Query(x,y) = Max { a[i] xor a[i+1] xor ... xor a[j] ; l ≤ i ≤ j ≤ r }.
  • 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[1] = 0 , lastans[i] = Query[i-1].

Given M queries, your program must output the results of these queries. (0 ≤ M ≤ 6000).

IMPORTANT : PROBLEM ENHANCED. ( I'M SO SORRY.. )

Input

  • The first line of the input file contains 2 numbers : N M.
  • In the second line, N numbers follow.
  • M lines follow, where line i contains 2 numbers xi and yi.

Output

Your program should output the results of the M queries, one query per line.

Example

Input:
3 3
1 4 3
0 1
0 1
4 3 Output:
5
7
7

题目:

对于每个询问,输出[L,R]区间的最大的连续异或值,强制在线。

解法: 分块+可持久化字典树

  1. 首先,分块,把每个点分属于一个块,belong[i]=(i-1)/sqrt(n) +1;
  2. 预处理得到每个块的左边界到右边的点的区间的最大异或,即如果(i-1)%sqrt(n)=0 ,则计算Maxxor[belong[i],j],(i<=j<=n)(这里很关键,不过先别管这里这么实现的,看完)
  3. 对于每个询问[L,R],由于我们预处理得到了[belong[L]+1,R]的最大异或和,现在只要计算[t,R]的最大异或和(L<=t<=belong[L]的右边界)。

-------------------------------------------嗯,看似行得通,怎么实现呢?----------------------------------------

首先,此题的分块没有暴力删除,没有添加等等操作,分块只是为了预处理,的得到多个区间的最大异或和。

对于第二步, 我们怎么实现呢,看似复杂度很大。但是我们对于MAXOR[i,j],充分利用到前面计算的结果,MAXOR[i,j]=max(MAXOR[i,j-1],num[j]^字典树)。

然后问题来了,字典树怎么限定边界呢? ------可持久化实现。

那么对于每个询问,只有[L,相应块的右边界]需要在持久化Trie里找最大,然后结合预先处理的[L的右边界+1,R]得到结果。

#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=;
struct nmphy
{
int n,m,a[maxn],G[][maxn];
int rt[maxn],sum[maxn*],ch[maxn*][],cnt;
int B,group[maxn],L; int swap(int &u,int &v) { u^=v; v^=u; u^=v; }
int Max (int &x,int y) { if(y>x) x=y;} void init()
{
scanf("%d%d",&n,&m);
n++; int tmp=;
for(int i=;i<=n;i++){ //这里i==1是为了把a[1]==0加进去。
scanf("%d",&a[i]);
a[i]^=a[i-];
tmp|=a[i]; //得到最长位。
}
L=; while(tmp) L++,tmp>>=; if(!L) L=;
for(int i=;i<=n;i++) insert(rt[i-],rt[i],a[i],L-);
} void insert(int x,int &y,int val,int pos)
{
sum[y=++cnt]=sum[x]+;
if(pos==) return ;
int d=(val>>pos)&;
ch[y][d^]=ch[x][d^];
insert(ch[x][d],ch[y][d],val,pos-);
} int query(int x,int y,int val)
{
int res=;
for(int i=L-;i>=;i--){
int d=(val>>i)&;
if(sum[ch[y][d^]]-sum[ch[x][d^]]>) {
res+=(<<i);
x=ch[x][d^];y=ch[y][d^];
}
else x=ch[x][d],y=ch[y][d];
} return res;
}
int cal(int x, int y, int v, int d) {
if (d < ) return ;
int p = v >> d & ; int tmp = sum[ch[y][p ^ ]] - sum[ch[x][p ^ ]];
if (tmp > ) return ( << d) + cal(ch[x][p ^ ], ch[y][p ^ ], v, d - );
else return cal(ch[x][p], ch[y][p], v, d - );
} void divide()
{
while(B*B<n) B++;
for(int i=;i<=n;i++) {
group[i]=(i-)/B+;
if((i-)%B==){
for(int j=i;j<=n;j++){
G[group[i]][j]=cal(rt[i],rt[j],a[j],L-);
Max(G[group[i]][j],G[group[i]][j-]);
}
}
}
} void solve()
{
int ans=,tmp,l,r;
for(int i=;i<=m;i++)
{
scanf("%d%d",&l,&r);
l=(l+(long long)ans)%(n-)+;
r=(r+(long long)ans)%(n-)+;
if(l>r) swap(l,r); r++;
ans=G[group[l]+][r];
for(int j=l;j<=r&&group[j]==group[l];j++){
tmp=cal(rt[l],rt[r],a[j],L-);
Max(ans,tmp);
}
printf("%d\n",ans);
}
}
}Tree;
int main()
{
Tree.init(); //输入,持久化Trie树
Tree.divide(); //分块,预处理块尾到后面的信息。
Tree.solve(); //快头之后的信息+块头前的暴力。
return ;
}

SPOJ MAXOR (分块 || 可持久化字典树 || 异或)(好题)的更多相关文章

  1. 【BZOJ 3261】最大异或和【可持久化字典树】

    题意 给出一个长度为n的整数序列,给出m个操作.操作有两种.1,Ax表示在序列结尾增加x.2,Qlrx表示找到一个位置p满足 l<=p<=r,使得a[p] xor a[p+1]xor... ...

  2. bzoj 3261 最大异或和 可持久化字典树(01树)

    题目传送门 思路: 由异或的性质可得,题目要求的式子可以转化成求$max(pre[n]^x^pre[i])$,$pre[i]$表示前缀异或和,那么我们现在就要求出这个东西,所以用可持久化字典树来求,每 ...

  3. HDU 4757 Tree 可持久化字典树

    Tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=4757 Des ...

  4. HDU - 6191 Query on A Tree (可持久化字典树/字典树合并)

    题目链接 题意:有一棵树,树根为1,树上的每个结点都有一个数字x.给出Q组询问,每组询问有两个值u,x,代表询问以结点u为根的子树中的某一个数与x的最大异或值. 解法一:dfs序+可持久化字典树.看到 ...

  5. 【HDU 6191】Query on A Tree 【可持久化字典树】

    题目 给出一棵有n个结点的树,树根是1,每个结点给出一个value.然后给出q个询问,每个询问给出两个整数u和x,你要在以u结点为根的子树中找出一个结点v,使得val[v] xor x最大, 并输出这 ...

  6. Hdu-4757 Tree(可持久化字典树+lca)

    题目链接:点这 我的github地址:点这     Problem Description   Zero and One are good friends who always have fun wi ...

  7. 51Nod XOR key —— 区间最大异或值 可持久化字典树

    题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1295 1295 XOR key  题目来源: HackerRa ...

  8. Codeforces 706D Vasiliy's Multiset(可持久化字典树)

    [题目链接] http://codeforces.com/problemset/problem/706/D [题目大意] 要求实现一个集合中的三个操作,1:在集合中加入一个元素x,2:从集合中删除一个 ...

  9. hdu 6191--Query on A Tree(持久化字典树)

    题目链接 Problem Description Monkey A lives on a tree, he always plays on this tree. One day, monkey A l ...

随机推荐

  1. Redis绑定多个ip地址

    Redis绑定多个ip地址 学习了:https://www.zhihu.com/question/20346112/answer/17157379 注意,用空格进行分隔 bind 127.0.0.1 ...

  2. Linux 主机被入侵后的处理案例

    Linux主机被入侵后的处理案例 提交 我的留言 加载中 已留言 一次Linux被入侵后的分析 下面通过一个案例介绍下当一个服务器被rootkit入侵后的处理思路和处理过程,rootkit攻击是Lin ...

  3. jquery_ajax 入门实例

    序:本文通过几个小样例,简单介绍怎样使用jqueryAjax异步载入. 1. $(selector).load(url,[data],[callback]) :加载远程HTML文件代码并插入DOM中. ...

  4. Eclipse 教程

    Eclipse 教程 Eclipse 是一个开放源代码的.基于 Java 的可扩展开发平台. Eclipse 是 Java 的集成开发环境(IDE),当然 Eclipse 也可以作为其他开发语言的集成 ...

  5. POJ 3978(求素数)

    知识点:      1.求素数的test,从2~sqrt(n):           2.假设数据非常多,能够用素数表记录,然后sum=prime[m]-prime[n]求得! ! !! !!! !! ...

  6. python(14)- 简单练习:登录账户失败三次,账户自动锁定

    题目需求:   1.输入用户名密码   2.认证成功后显示欢迎信息   3.输错三次后锁定 #读取注册用户的信息,用户名,密码,输错次数,写入字典中 user={} with open("D ...

  7. Hadoop 50090端口的页面, Replication的数字是真实的文件备份数吗? (不是)

    红色方框的部分,代表Hadoop系统,人工设定的文件备份数,但不是实际的备份数.文件备份数 不会大于集群机器的总数目(因为备份文件不会同时存在一台机器上,这样就没有意义),所以如果总集群数目是2,即使 ...

  8. UVA 10042 Smith Numbers(数论)

    Smith Numbers Background While skimming his phone directory in 1982, Albert Wilansky, a mathematicia ...

  9. angularJS 常用插件指令

    长时间没有登入博客园了,今天突然想了想,当初开这个的目的,其实就是为了记录你当下的一个状态和累计一些问题,所以记录这些还是很有意义,毕竟不是什么牛,靠脸又吃不饱的这个年代,需要留下一些东西给自己看也好 ...

  10. Active Directory的LDAP协议与DN(Distinguished Name)详解

    前言 光copy几段代码的文章没什么意思,本章上最基础的代码,主要是为了从编程方面聊LDAP和DN,其它的后面聊,一步步慢慢来吧. Active Directory编程须知 1.域控服务器: Wind ...