BZOJ2741【FOTILE模拟赛】L

题面

$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$。

思路

本题是在区间里面找区间,直接做比较困难,那么让我们从简单开始:假如询问一个序列中的区间异或和最大,那么该怎么做,不难发现只要将序列的前缀异或和加入$trie$树中然后对于每个前缀查一次与它异或的最大值即可。那么此时拓展到了区间,不是一整段序列了,怎么办?考虑分块,$f[i][j]$表示从第$i$块起点开始到$j$的区间最大连续异或和,这个玩意显然是可以$O(Nsqrt(N))$推得的,那么预处理出$f[i][j]$后对于一个没有跨块的询问直接暴力,对于跨块的询问暴力查询左边边角即可,不过要从$l-1$开始,因为开头可选,然后和$f[num[l]+1][r]$比较即可。

代码

#include<bits/stdc++.h>
#define LL long long
#define Maxn 12005
using namespace std;
LL num[Maxn],N,M,sum[Maxn],rt[Maxn],len,tot,f[1025][Maxn],cnt=0,o;
LL lastans=0;
struct trie{LL ls,rs,size;}tree[300*Maxn];
struct block{LL l,r;}b[1025];
inline void read(LL &x)
{
	LL f=1;x=0;char ch=getchar();
	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
	while (isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
	x*=f;
}
inline void insert(LL pre,LL &root,LL i,LL x)
{
	root=++cnt; 
	tree[root]=tree[pre];
	tree[root].size++;
	if (i<0) return; 
	if ((x>>i)&1) insert(tree[pre].rs,tree[root].rs,i-1,x);
	else insert(tree[pre].ls,tree[root].ls,i-1,x);
}
inline LL query(LL pre,LL root,LL i,LL x)
{
	if (i<0) return 0;
	if ((x>>i)&1)
	{
		if (tree[tree[root].ls].size-tree[tree[pre].ls].size>=1) return query(tree[pre].ls,tree[root].ls,i-1,x)+(1<<i);
		else return query(tree[pre].rs,tree[root].rs,i-1,x);
	}
	else
	{
		if (tree[tree[root].rs].size-tree[tree[pre].rs].size>=1) return query(tree[pre].rs,tree[root].rs,i-1,x)+(1<<i);
		else return query(tree[pre].ls,tree[root].ls,i-1,x);
	}
}
int main()
{
	//freopen("1.in","r",stdin);
	memset(f,0,sizeof(f));
	read(N),read(M);
	insert(rt[0],rt[1],60,0);
	for (LL a,i=2;i<=N+1;i++) read(a),sum[i]=sum[i-1]^a,insert(rt[i-1],rt[i],60,sum[i]); 
	len=(LL)sqrt(N+1);
	tot=(N+1)/len;
	if ((N+1)%len) tot++;
	for (LL i=1;i<=tot;i++)
	{
		b[i].l=(i-1)*len+1;
		b[i].r=i*len;
		f[i][b[i].l]=sum[b[i].l]^sum[b[i].l-1];
		for (LL j=b[i].l+1;j<=N+1;j++) f[i][j]=max(f[i][j-1],query(rt[b[i].l-1],rt[j],60,sum[j]));
	}
	b[tot].r=N+1;
	for (LL i=1;i<=N+1;i++) num[i]=(i-1)/len+1;
	while (M--)
	{
		o++;
		LL x,y;
		read(x),read(y);
		LL l=(LL)(1LL*x+1LL*lastans)%N+1LL,r=(LL)(1LL*y+1LL*lastans)%N+1LL;
		if (l>r) swap(l,r);
		l++,r++;
		lastans=0;
		if (num[l]==num[r])
		{
			for (LL i=l-1;i<=r;i++) lastans=max(lastans,query(rt[l-1],rt[r],60,sum[i]));
		}
		else
		{
			for (LL i=l-1;i<=b[num[l]].r;i++) lastans=max(lastans,query(rt[l-1],rt[r],60,sum[i]));
			lastans=max(lastans,f[num[l]+1][r]);
		}
		cout<<lastans<<endl;
	} 
	return 0;
}
暂无评论

发送评论 编辑评论


|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇