【BZOJ2741】FOTILE模拟赛 L
2016-02-26 16:39
267 查看
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
可持久化Trie+分块 感觉这东西挺厉害的..我是第一次写可持久化Trie
记前缀异或和,用分块维护
因此,我们可以发现每个块的左端点与另一个任意位置的数值异或和中选一个最大值,就是对应区间的最大异或和
所以记录一下每个块左端点与另一个位置之间最大两数异或和,用f[i][j]表示,用trie进行DP.
然后对每个询问,整块的用DP值整块搞,零散的放进trie跑暴力.
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
可持久化Trie+分块 感觉这东西挺厉害的..我是第一次写可持久化Trie
记前缀异或和,用分块维护
因此,我们可以发现每个块的左端点与另一个任意位置的数值异或和中选一个最大值,就是对应区间的最大异或和
所以记录一下每个块左端点与另一个位置之间最大两数异或和,用f[i][j]表示,用trie进行DP.
然后对每个询问,整块的用DP值整块搞,零散的放进trie跑暴力.
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define GET (ch>='0'&&ch<='9') #define SIZE 800010 #define MAXN 12010 using namespace std; void in(int &x) { char ch=getchar();x=0; while (!GET) ch=getchar(); while (GET) x=x*10+ch-'0',ch=getchar(); } int n,m,size,cnt,num,lastans; int a[MAXN],root[MAXN],ls[SIZE],rs[SIZE],sz[SIZE],f[120][MAXN]; void insert(int x,int &y,int val,int dep) { sz[y=++num]=sz[x]+1; if (dep<0) return; ls[y]=ls[x];rs[y]=rs[x]; if (val&(1<<dep)) insert(rs[x],rs[y],val,dep-1); else insert(ls[x],ls[y],val,dep-1); } int query(int x,int y,int val) { int ret=0; for (int i=30;i>=0;i--) { int tmp=val&(1<<i); if (!tmp) { if (sz[rs[y]]-sz[rs[x]]!=0) ret+=(1<<i),x=rs[x],y=rs[y]; else x=ls[x],y=ls[y]; } else { if (sz[ls[y]]-sz[ls[x]]!=0) ret+=(1<<i),x=ls[x],y=ls[y]; else x=rs[x],y=rs[y]; } } return ret; } int main() { in(n);in(m);size=(int)(sqrt(n));cnt=n/size+(bool)(n%size); for (int i=1;i<=n;i++) in(a[i]),a[i]^=a[i-1]; for (int i=1;i<=n;i++) insert(root[i-1],root[i],a[i],30); for (int i=1;i<=cnt;i++) for (int j=(i-1)*size+1;j<=n;j++) { f[i][j]=max(f[i][j-1],query(root[(i-1)*size],root[j],a[j])); if (i==1) f[i][j]=max(f[i][j],a[j]); } while (m--) { int l,r;lastans%=n;in(l);in(r);l=(l+lastans)%n+1;r=(r+lastans)%n+1; if (l>r) swap(l,r);l--;int t;lastans=t=0; for (int i=1;i<=cnt;i++) if (l<=(i-1)*size+1&&r>=(i-1)*size+1) { lastans=f[i][r];t=i;break; } if (t) for (int j=l;j<=(t-1)*size+1;j++) lastans=max(lastans,query(root[l-1],root[r],a[j])); else for (int j=l;j<=r;j++) lastans=max(lastans,query(root[l-1],root[r],a[j])); printf("%d\n",lastans); } }
相关文章推荐
- [BZOJ2038][2009国家集训队][莫队][分块]小z的袜子
- Codeforces538F A Heap of Heaps【分块+差分求前缀和】
- 大矩阵的分块乘法及matlab实现
- Hadoop分块和分片
- bzoj-2741 L
- bzoj-3585 mex
- bzoj-2051 A Problem For Fun
- 算法马拉松8(差和问题)
- 1290 Counting Diff Pairs
- 【Violet 6】【BZOJ2724】蒲公英
- 【BZOJ4320】Homework
- 【BZOJ4216】Pig
- [2009国家集训队]小Z的袜子(hose) 分块做法
- NBUT 1457 分块
- codeforces #307 E. GukiZ and GukiZiana (分块)
- Codeforces Round #307 (Div. 2)E. GukiZ and GukiZiana(分块)
- 【分块】 CF 551 E GukiZ and GukiZiana
- Codeforces Round #307 (Div. 2) E. GukiZ and GukiZiana (分块)
- Codeforces Gym 100589A Queries on the Tree(树状数组+分块)
- HDU 4467 Graph(分块)