CodeForces

题目

传送门

解法

暴力用线段树维护,线性基合并是 (mathcal O(nlog nlog^2 c)) 的。

考虑线性基计算最大值时从最高位向低位异或,如果第 (i) 位因此变成 (1) 就异或。

首先按 (r) 排序,将 (1) 到当前 (r)(a_i) 加入线性基。令 (lim[i]) 为第 (i) 位为 (1) 的最大位置(注意这不一定是最初态)。

先看看 Insert()

void Insert(int x,int pos) {
    fep(i,20,0) 
        if((x>>i)&1) {
            if(!d[i]) {d[i]=x,lim[i]=pos; break;}
            if(pos>lim[i]) swap(pos,lim[i]),swap(x,d[i]);
            x^=d[i];
        }
}

我们将位置大的优先选择。而且不会出现 (a_x) 被位置小于自己的数 (a_y) 异或导致 (a_x ext{xor} a_y) 存在必须保证取到位置 (y) 而不是传进去的参数 (x)

那么最后的线性基异或和最大值异或的条件就多了一个:传进去的 (l)(左边界)小于等于 (lim[i])

这道题还可以离线做,只要将 (r) 全插进去就行了,时间复杂度 (mathcal O(nlog n))

可以离线与分治。

二分数组下标,求出 (mid) 开始的后缀线性基与前缀线性基。对于跨过 (mid) 的询问,将其对应的前缀与后缀合并起来求得答案,其它的询问递归处理。

每个询问只会合并一次,故时间复杂度 (mathcal O(qlog^2 c))

对于分治部分,有一个 ( ext{OI Wiki}) 的主定理:

此题 (a=b=2,k=1),故时间复杂度 (mathcal O(nlog^2 n))

总时间复杂度 (mathcal O(nlog^2 n+qlog^2 c))

代码

#include <cstdio>

#define rep(i,_l,_r) for(register signed i=(_l),_end=(_r);i<=_end;++i)
#define fep(i,_l,_r) for(register signed i=(_l),_end=(_r);i>=_end;--i)
#define erep(i,u) for(signed i=head[u],v=to[i];i;i=nxt[i],v=to[i])
#define efep(i,u) for(signed i=Head[u],v=to[i];i;i=nxt[i],v=to[i])
#define print(x,y) write(x),putchar(y)

template <class T> inline T read(const T sample) {
    T x=0; int f=1; char s;
    while((s=getchar())>'9'||s<'0') if(s=='-') f=-1;
    while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
    return x*f;
}
template <class T> inline void write(const T x) {
    if(x<0) return (void) (putchar('-'),write(-x));
    if(x>9) write(x/10);
    putchar(x%10^48);
}
template <class T> inline T Max(const T x,const T y) {if(x>y) return x; return y;}
template <class T> inline T Min(const T x,const T y) {if(x<y) return x; return y;}
template <class T> inline T fab(const T x) {return x>0?x:-x;}
template <class T> inline T gcd(const T x,const T y) {return y?gcd(y,x%y):x;}
template <class T> inline T lcm(const T x,const T y) {return x/gcd(x,y)*y;}
template <class T> inline T Swap(T &x,T &y) {x^=y^=x^=y;}

#include <iostream>
#include <algorithm>
using namespace std;

const int maxn=5e5+5;

int n,a[maxn],q,ans[maxn],d[50],lim[50];
struct node {
	int l,r,id;
	
	bool operator < (const node t) {
		return r<t.r;
	}
} s[maxn];

void Insert(int x,int pos) {
	fep(i,20,0) 
		if((x>>i)&1) {
			if(!d[i]) {d[i]=x,lim[i]=pos; break;}
			if(pos>lim[i]) swap(pos,lim[i]),swap(x,d[i]);
			x^=d[i];
		}
}

int calc(int l) {
	int ret=0;
	fep(i,20,0)
		if(l<=lim[i] && ret<(d[i]^ret)) ret^=d[i];
	return ret;
}

int main() {
	n=read(9);
	rep(i,1,n) a[i]=read(9);
	q=read(9);
	rep(i,1,q) s[i].id=i,s[i].l=read(9),s[i].r=read(9);
	sort(s+1,s+q+1);
	int Pointer=0;
	rep(i,1,q) {
		while(Pointer<s[i].r) {
			++Pointer;
			Insert(a[Pointer],Pointer);
		}
		ans[s[i].id]=calc(s[i].l);
	}
	rep(i,1,q) print(ans[i],'
');
	return 0;
}
原文地址:https://www.cnblogs.com/AWhiteWall/p/14407606.html