#线性基#CF1100F Ivan and Burgers

题目传送门


分析

线段树上直接维护线性基是三个log的。(一定要合并)

考虑一种分治做法,在 [l,mid](mid,r] 的询问分治处理,

跨过 [mid,mid+1] 的维护 [i,mid] 的线性基和 [mid+1,j] 的线性基,

询问时合并起来,复杂度就是 O((n+Q)lognlogmax{ai})

还有一种做法就是以右端点为基准,然后尽量让线性基中的数字位置靠近右端点,插入时能替换就替换。

可以在线询问,线性基的数位置在左端点或之后就可以参与询问,这样时间复杂度是 O((n+Q)logmax{ai})


代码

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=500011; int n;
int iut(){
	int ans=0; char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=ans*10+c-48,c=getchar();
	return ans;
}
void print(int ans){
	if (ans>9) print(ans/10);
	putchar(ans%10+48);
}
struct Vector_Space{
	int re[20],tim[20];
	void BUILD(){
		memset(re,0,sizeof(re));
		memset(tim,0,sizeof(tim));
	}
	void Insert(int x,int j){
		for (int i=19;~i;--i)
		if ((x>>i)&1){
			if (!re[i]) {re[i]=x,tim[i]=j; return;}
		    else{
		    	if (tim[i]<j) swap(tim[i],j),swap(re[i],x);
		    	x^=re[i];
			}
		}
	}
	int query(int l){
		int x=0;
		for (int i=19;~i;--i)
		    if (tim[i]>=l&&(x^re[i])>x) x^=re[i];
		return x;
	}
}H[N];
int main(){
	n=iut();
	for (int i=1;i<=n;++i){
		int x=iut();
		H[i]=H[i-1],H[i].Insert(x,i);
	}
	for (int Q=iut();Q;--Q){
		int l=iut(),r=iut();
		print(H[r].query(l)),putchar(10);
	}
	return 0;
}
posted @   lemondinosaur  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
历史上的今天:
2020-03-28 「Cnoi2020」Cirno's Easy Round
点击右上角即可分享
微信分享提示