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范围内。
Source
思路(参考自http://blog.csdn.net/oceanlight/article/details/14104185):
把求一段区间的异或和变成求两个值得异或,也就是令b[i]=a[1]^a[2]^...^a[i],然么求a[i]^a[i+1]^...^a[j]就变成求b[i-1]^b[j];
首先分块,维护每一块的开头到j的最大连续和,其中j大于这一块的开头的位置
dp[i][j]=max(dp[i][j-1],query(b[i],K,root[st],root[j]));
query的操作利用可持久化的Trie
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=12010;
const int K=31;
typedef long long LL;
int A[maxn],B[maxn];
int N,M,cnt;
int size;
int dp[200][maxn];
struct Node
{
Node *son[2];
int num;
}node[maxn*300];
Node *root[maxn],*null;
struct Trie
{
Node* insert(int x,int depth,Node *root)
{
Node *newroot=&node[cnt++];
newroot->son[0]=root->son[0];
newroot->son[1]=root->son[1];
newroot->num=root->num+1;
if(depth<0)return newroot;
int p=((x>>depth)&1);
newroot->son[p]=insert(x,depth-1,root->son[p]);
return newroot;
}
int query(int x,int depth,Node *rootl,Node *rootr)
{
if(depth<0)return 0;
int p=((x>>depth)&1);
if(rootr->son[p^1]->num>rootl->son[p^1]->num)
return (1<<depth)+query(x,depth-1,rootl->son[p^1],rootr->son[p^1]);
return query(x,depth-1,rootl->son[p],rootr->son[p]);
}
}tree;
void init()
{
cnt=0;
root[0]=null=&node[cnt++];
null->son[0]=null->son[1]=null;
null->num=0;
}
void solve()
{
for(int i=1;i<=N;i++)
root[i]=tree.insert(B[i],K,root[i-1]);
}
int cal(int l,int r)
{
l--;
int x_pos=(l-1)/size;
int y_pos=(r-1)/size;
int ans=0;
if(y_pos>x_pos)ans=dp[x_pos+1][r];
for(int i=l;i<min((x_pos+1)*size+2,r);i++)
ans=max(ans,tree.query(B[i],K,root[l],root[r]));
return ans;
}
int main()
{
while(scanf("%d%d",&N,&M)!=EOF)
{
memset(B,0,sizeof(B));
memset(dp,0,sizeof(dp));
for(int i=1;i<=N;i++)
{
scanf("%d",&A[i]);
B[i]=B[i-1]^A[i];
}
size=sqrt(N);
init();
solve();
for(int i=1;i<=N;i++)
{
int x_pos=(i-1)/size;
for(int j=0;j<=x_pos;j++)
{
int y_pos=j*size+1;
dp[j][i]=max(dp[j][i-1],tree.query(B[i],K,root[y_pos],root[i]));
}
}
int lastans=0;
while(M--)
{
int x,y;
scanf("%d%d",&x,&y);
int l=min((x+lastans%N)%N+1,(y+lastans%N)%N+1);
int r=max((x+lastans%N)%N+1,(y+lastans%N)%N+1);
int ans=cal(l,r);
printf("%d\n",ans);
lastans=ans;
}
}
return 0;
}