bzoj 2741: 【FOTILE模拟赛】L
2015-06-02 16:21
218 查看
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
HINTN=12000,M=6000,x,y,Ai在signed longint范围内。
分块+可持久化trie
用f[i][j]表示第i块开头到位置j的最大ans
f[i][j]=max(f[i][j-1],ask(head[i],j-1,a[j]))
这里处理是nsqrt(n)logn
然后每次询问的时候把整块的一起处理
再枚举前面部分的位置,更新ans即可
#include<cmath> #include<cstdio> #include<string> #include<cstring> using namespace std; struct tree { int l,r; int ll,rr; }tr[5000001]; int root[600001]; long long px[32]; int tot; inline int add(int p,int d,int dep) { if(dep==31) return 0; if(d>=px[dep]) { tot++; int pp=tot; tr[pp].l=tr[p].l; tr[pp].ll=tr[p].ll; tr[pp].r=add(tr[p].r,d-px[dep],dep+1); tr[pp].rr=tr[p].rr+1; return pp; } else { tot++; int pp=tot; tr[pp].l=add(tr[p].l,d,dep+1); tr[pp].ll=tr[p].ll+1; tr[pp].r=tr[p].r; tr[pp].rr=tr[p].rr; return pp; } } inline int ask(int l,int r,int x,int dep) { if(dep==31) return 0; if(x>=px[dep]) { if(tr[r].ll-tr[l].ll>0) return px[dep]+ask(tr[l].l,tr[r].l,x-px[dep],dep+1); else return ask(tr[l].r,tr[r].r,x-px[dep],dep+1); } else { if(tr[r].rr-tr[l].rr>0) return px[dep]+ask(tr[l].r,tr[r].r,x,dep+1); else return ask(tr[l].l,tr[r].l,x,dep+1); } } int a[100001]; int x[100001]; int belong[100001]; int head[1001]; int f[1001][20001]; int main() { // freopen("data.in","r",stdin); // freopen("data.out","w",stdout); long long n; int m; scanf("%lld%d",&n,&m); int i,j; px[0]=1; for(i=1;i<=30;i++) px[i]=px[i-1]*2; for(i=0;i<=15;i++) { int t=px[i]; px[i]=px[30-i]; px[30-i]=t; } root[0]=1; add(0,0,0); for(i=1;i<=n;i++) { scanf("%lld",&x[i]); a[i]=(a[i-1]^x[i]); root[i]=tot+1; add(root[i-1],a[i],0); } int nt=sqrt(n); int nx=0; for(i=1;i<=n;i++) { belong[i]=(i-1)/nt+1; if(belong[i]!=belong[i-1]) { nx++; head[belong[i]]=i; } } head[nx+1]=n+1; for(i=1;i<=nx;i++) { f[i][head[i]]=x[head[i]]; for(j=head[i]+1;j<=n;j++) { int rt=head[i]-2; if(rt<0) rt=0; else rt=root[rt]; f[i][j]=max(f[i][j-1],ask(rt,root[j-1],a[j],0)); } } long long s,t; long long last=0; for(i=1;i<=m;i++) { scanf("%lld%lld",&s,&t); int ss=(s+last)%n+(long long)1,tt=(t+last)%n+(long long)1; s=min(ss,tt); t=max(ss,tt); /* if(s==t) { printf("%d\n",x[s]); continue; }*/ int nxt=belong[s]; if(head[nxt]!=s) nxt++; int ans=f[nxt][t]; for(j=s;j<=min(head[nxt]-1,(int)t);j++) { ans=max(ans,ask(root[s-1],root[t],a[j-1],0)); } printf("%lld\n",ans); last=ans; } return 0; }
相关文章推荐
- android数据保存
- vs2010安装报错问题
- java socket实现全双工通信
- 非计算机专业研究生自学进BAT的经历!(转)
- absolute、relative,toggle()
- Android 获取外置SD卡
- 品牌故事
- sqoop oracle 到hdfs
- 飞机订票系统
- Java学习笔记之网络编程
- java 的synchronized详解
- 线程的生命周期及状态的管理
- Xen虚拟机磁盘镜像模板制作(一)—Windows Server 2008(2012)
- 手机测试一些知识点
- Jmeter报告分析
- 【RAC】将RAC备份集恢复为单实例数据库
- 正则表达式全部符号解释
- VS2010安装MSDN Library
- 【C#】利用反射机制创建对象
- HashMap遍历:entrySet和keySet的比较