欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Codeforces - Ivan and Burgers

程序员文章站 2022-05-27 20:26:48
...

题目链接:Codeforces - Ivan and Burgers


读题之后发现,比较显然的做法就是线段树维护线性基。(不过复杂度过高,一直没卡过去)。

我们可以尝试离线的做法、先按照右端点排序。

一次插入线性基当中,怎么保证当前对答案异或的时候,这个基底是存在于[l,r]当中的呢?我们每次插入线性基的时候记录一个时间戳即可。如果当前的时间戳大于等于L,就可以异或。

因为我们是从前往后面扫,所以时间戳每次选最大的更新。


卡常失败的代码:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=5e5+10;
int n,c[N],q;
char *fs,*ft,buf[1<<20];
#define gc() (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<20,stdin),fs==ft))?0:*fs++;
inline int read(){
    int x=0,f=1; char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=gc();}
    return x*f;
}
struct lb{
	int d[30];
	inline void insert(int x){
		for(int i=20;i>=0;i--)	if(x>>i&1){
			if(d[i])	x^=d[i];
			else{d[i]=x;	return ;}
		}
	}
	inline void insert(lb &x){
		for(int i=20;i>=0;i--)	if(x.d[i])	insert(x.d[i]);
	}
}t[N<<2],res;
void change(int p,int l,int r,int x,int v){
	t[p].insert(v);
	if(l==r)	return ;	int mid=l+r>>1;
	if(x<=mid)	change(p<<1,l,mid,x,v);
	else	change(p<<1|1,mid+1,r,x,v);
}
void ask(int p,int l,int r,int ql,int qr){
	if(l==ql&&r==qr)	return res.insert(t[p]),void();
	int mid=l+r>>1;
	if(qr<=mid)	ask(p<<1,l,mid,ql,qr);
	else if(ql>mid)	ask(p<<1|1,mid+1,r,ql,qr);
	else ask(p<<1,l,mid,ql,mid),ask(p<<1|1,mid+1,r,mid+1,qr);
}
inline int calc(){
	int s=0;
	for(int i=20;i>=0;i--)	if((s^res.d[i])>s)	s^=res.d[i];
	return s;
}
signed main(){
	n=read();
	for(int i=1;i<=n;i++)	c[i]=read(),change(1,1,n,i,c[i]);
	q=read();
	for(int i=1,l,r;i<=q;i++){
		l=read(),r=read();	memset(res.d,0,sizeof res.d);
		ask(1,1,n,l,r);	printf("%d\n",calc());
	}
	return 0;
}

AC代码:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=5e5+10;
int n,d[25],dfn[25],c[N],q,res[N];
struct node{int l,r,id;}t[N];
char *fs,*ft,buf[1<<20];
#define gc() (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<20,stdin),fs==ft))?0:*fs++;
inline int read(){
    int x=0,f=1; char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=gc();}
    return x*f;
}
int cmp(node a,node b){return a.r<b.r;}
inline void insert(int x,int id){
	for(int i=20;i>=0;i--)	if(x>>i&1){
		if(!d[i]){d[i]=x;	dfn[i]=id;	return;}
		if(dfn[i]<id)	swap(d[i],x),swap(dfn[i],id);
		x^=d[i];
	}
}
inline int ask(int id){
	int res=0;
	for(int i=20;i>=0;i--)	if(dfn[i]>=id&&(res^d[i])>res)	res^=d[i];
	return res;
}
signed main(){
	n=read();
	for(int i=1;i<=n;i++)	c[i]=read();
	q=read();
	for(int i=1;i<=q;i++)	t[i].l=read(),t[i].r=read(),t[i].id=i;
	sort(t+1,t+1+q,cmp);	int ed=1;
	for(int i=1;i<=q;i++){
		while(ed<=t[i].r)	insert(c[ed],ed),ed++;
		res[t[i].id]=ask(t[i].l);
	}
	for(int i=1;i<=q;i++)	printf("%d\n",res[i]);
	return 0;
}