您的位置:首页 > 其它

BZOJ2741: 【FOTILE模拟赛】L

2015-12-22 21:35 316 查看
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2741

分块+可持久化trie

f[i][j]表示第i块到第j个数的最大答案。可以通过n^1.5时间内维护出来。

然后对于询问就前面那一段暴力找和块的答案相比较就好了。

然后似乎一定要插一个0 。。。

#include<cstring>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<set>
#include<cmath>
#define rep(i,l,r) for (int i=l;i<=r;i++)
#define down(i,l,r) for (int i=l;i>=r;i--)
#define clr(x,y) memset(x,y,sizeof(x))
#define maxn 20050
#define inf int(1e9)
#define maxd 30
#define mm 1000000007
#define ll long long
using namespace std;
int a[maxn];
int f[130][maxn],s[maxn*301][2],sum[maxn*301],root[maxn],pos[maxn];
int n,l,r,m,cnt,ans,len,num;
int read(){
int x=0,f=1; char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
void add(int d,int x,int &y,int val){
y=++cnt; sum[y]=sum[x]+1;
if (d<0) return;
s[y][0]=s[x][0]; s[y][1]=s[x][1];
int p=(val>>d)&1;
add(d-1,s[x][p],s[y][p],val);
}
int ask(int d,int x,int y,int val){
if (d<0) return 0;
int p=(val>>d)&1;
if (sum[s[y][p^1]]-sum[s[x][p^1]]>0) return (1<<d)+ask(d-1,s[x][p^1],s[y][p^1],val);
else return ask(d-1,s[x][p],s[y][p],val);
}
void getans(int l,int r){
ans=0;
int lx=pos[l],rx=pos[r];
if (lx<rx) ans=f[lx+1][r];
rep(i,l,min(lx*len,r)) ans=max(ans,ask(maxd,root[l],root[r+1],a[i]));
printf("%d\n",ans);
}
int main(){
n=read(); m=read();
len=sqrt(n);
rep(i,1,n) a[i]=read(),a[i]=a[i]^a[i-1],pos[i]=i/len+1;
rep(i,0,n) add(maxd,root[i],root[i+1],a[i]);
num=n/len+1;
rep(i,1,num) {
int now=(i-1)*len;
rep(j,now,n) f[i][j]=max(f[i][j-1],ask(maxd,root[now],root[j+1],a[j]));
}
ans=0;
rep(i,1,m){
int x=read(),y=read();
x=((ll)x+ans)%n+1; y=((ll)y+ans)%n+1;
l=min(x,y); r=max(x,y);
getans(l-1,r);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: