MAXOR

前言

边界条件,烦人!(╯‵□′)╯︵┻━┻

题目

SPOJ

洛谷(有中文题面)

一句话题意:区间询问子区间异或和最大值。

讲解

其实做法很简单,将 (a_i) 做一个前缀异或和,然后分块+可持久化Trie就行了。

但是我们注意这样一个问题:如果我们要表示一个区间 ([l,r]) 的异或和,我们需要用 (a_{l-1}oplus a_{r}),对应到Trie上,(l-1) 是要被包含的,所以我们传的两个根应该是 (rt_{l-2},rt_r)

显然会有越界的问题,我最开始想的是在前面放个 (0),但是这样写很麻烦。而且我没调出来

但其实这种边界用 (a_{l-1})([l,r]) 即可。

代码

//12252024832524
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define TT template<typename T>
using namespace std; 

typedef long long LL;
const int MAXN = 12005;
const int MAXB = 150;
int n,m,B,ans;
int a[MAXN];

LL Read()
{
	LL x = 0,f = 1;char c = getchar();
	while(c > '9' || c < '0'){if(c == '-')f = -1;c = getchar();}
	while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
	return x * f;
}
TT void Put1(T x)
{
	if(x > 9) Put1(x/10);
	putchar(x%10^48);
}
TT void Put(T x,char c = -1)
{
	if(x < 0) putchar('-'),x = -x;
	Put1(x); if(c >= 0) putchar(c);
}
TT T Max(T x,T y){return x > y ? x : y;}
TT T Min(T x,T y){return x < y ? x : y;}
TT T Abs(T x){return x < 0 ? -x : x;}

int ID(int x){return (x-1)/B;}
int FI[MAXN];

int tot,rt[MAXN];
struct Trie
{
	int ch[2],cnt;
}t[MAXN * 32];
int newnode(){++tot;t[tot].ch[0] = t[tot].ch[1] = t[tot].cnt = 0;return tot;}
void Add(int lst,int &x,int val,int rk)
{
	if(!x || x == lst) x = newnode(),t[x] = t[lst];
	++t[x].cnt;
	if(rk < 0) return;
	bool to = val >> rk & 1;
	Add(t[lst].ch[to],t[x].ch[to],val,rk-1);
}
int Query(int lst,int x,int val,int rk,int s)
{
	if(rk < 0) return s;
	bool to = (val >> rk & 1) ^ 1;
	if(t[t[x].ch[to]].cnt-t[t[lst].ch[to]].cnt) return Query(t[lst].ch[to],t[x].ch[to],val,rk-1,s|(1<<rk));
	else return Query(t[lst].ch[to^1],t[x].ch[to^1],val,rk-1,s);
}
int MAX[MAXB][MAXB];

int main()
{
//	freopen("data.in","r",stdin);
//	freopen("mine.out","w",stdout);
	n = Read(); m = Read();
	for(int i = 1;i <= n;++ i) Add(rt[i-1],rt[i],a[i] = a[i-1]^Read(),30);
	B = ceil(sqrt(1.0*n*n/m/2));
	for(int i = 1;i <= n;i += B)
	{
		int now = 0;
		FI[ID(i)] = i;
		for(int j = i;j <= n;++ j)
		{
			now = Max(now,Query(rt[i-1],rt[j-1],a[j],30,0));
			now = Max(now,a[j]^a[i-1]);
			if((ID(j)^ID(j+1)) || j == n) MAX[ID(i)][ID(j)] = now;
		}
	}
	while(m --> 0)
	{
		int x = Read(),y = Read();
		int L = (x+0ll+ans)%n+1,R = (y+0ll+ans)%n+1;
		int l = Min(L,R),r = Max(L,R);
		if(ID(l)+1 >= ID(r))
		{
			ans = Query(rt[l-1],rt[r],a[l-1],30,0);
			for(int i = l;i <= r;++ i) ans = Max(ans,Query(rt[l-1],rt[i-1],a[i],30,0));
			Put(ans,'
');
		}
		else
		{
			L = ID(l)+1,R = ID(r)-1;
			ans = MAX[L][R];
			L = FI[L];
			ans = Max(ans,Query(rt[l-1],rt[r],a[l-1],30,0));
			for(int i = l;i < L;++ i) ans = Max(ans,Query(rt[l-1],rt[r],a[i],30,0));
			for(int i = FI[ID(r)];i <= r;++ i) ans = Max(ans,Query(rt[l-1],rt[i],a[i],30,0));
			Put(ans,'
');
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/PPLPPL/p/15291262.html