BZOJ - 2741: 【FOTILE模拟赛】L 分块+可持久化数据结构

来源:互联网 发布:solaris和centos 编辑:程序博客网 时间:2024/05/17 20:23

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范围内。

Source

By seter

思路(参考自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;}






0 0