Codeforces Round #532 (Div. 2) F 线性基(新坑) + 贪心 + 离线处理

https://codeforces.com/contest/1100/problem/F

题意

一个有n个数组c[],q次询问,每次询问一个区间的子集最大异或和

题解

  • 单问区间子集最大异或和,线性基能处理,但是这次多次询问,假如每次重新建立基向量会超时
  • 考虑区间的优先级,假如我只插入不删除的话,区间的优先级和左端点没有关系
  • 贪心一下,只保留后面插入的基,这样就可以离线解决询问,然后查询的时候需要判基的位置是不是在左端点后面

代码

#include<bits/stdc++.h>
#define ft first
#define se second
#define pii pair<int,int>
#define mk make_pair
#define MAXN 500005
using namespace std;
vector<pii>G[MAXN];
int c[MAXN],n,i,q,j,ans[MAXN],B[30],pos[30],l,r;

void add(int x,int p){
	for(int i=20;i>=0;i--){
		if(x>>i&&1){
			if(!B[i]){
				pos[i]=p;
				B[i]=x;
			}
			if(p>pos[i])swap(p,pos[i]),swap(x,B[i]);
			x^=B[i];
		}
	}
}
int main(){
	cin>>n;
	for(i=1;i<=n;i++)scanf("%d",&c[i]);
	cin>>q;
	for(i=1;i<=q;i++){
		scanf("%d%d",&l,&r);
		G[r].push_back(mk(i,l));
	}
	for(i=1;i<=n;i++){
		add(c[i],i);
		for(auto x:G[i]){
			for(j=20;j>=0;j--){
				if(pos[j]>=x.se)ans[x.ft]=max(ans[x.ft]^B[j],ans[x.ft]);
			}
		}
	}
	for(i=1;i<=q;i++)printf("%d\n",ans[i]);
}

猜你喜欢

转载自www.cnblogs.com/VIrtu0s0/p/10631513.html
今日推荐