[2019HDU多校第一場][HDU 6579][B. Operation] 線性基

 題意:操作1問區間[l,r]異或和最大,操作2讓末尾添加一個數x

l = (l^las)%n+1.  r = (r^las)%n+1. if(l>r)swap(l,r);              x = x^las 。

其中las是上一次操作1的答案,初始爲0.

解:讓[ 1,i ]區間每個基底儘量靠近 i 這個位置和這個位置的值。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e6+4;
int n,m,t;
int tp,las = 0;
int base[maxn][33],pos[maxn][33],bs[33],ps[33];
void add(int x,int id){
	for(int i=30;i>=0;i--){
		if(x&(1ll<<i)){
			if(!bs[i]){
				bs[i] = x;
				ps[i] = id;
				break;
			}
			if(ps[i]<id){
				swap(bs[i],x);
				swap(ps[i],id);
			}
			x^=bs[i];
		}
	}
} 
int main()
{
	
	scanf("%d",&t);
	while(t--){
		scanf("%d %d",&n,&m);
		for(int i=0;i<=30;i++)bs[i] = 0,ps[i] = 0;
		for(int i=1;i<=n;i++){
			scanf("%d",&tp);
			add(tp,i);
			for(int j=30;j>=0;j--)base[i][j] = bs[j],pos[i][j] = ps[j];
		}
		las = 0;
		int l,r,op,x;
		while(m--){
			scanf("%d",&op);
			if(op==1){
				scanf("%d",&x);
				x^=las;	n++; 
				add(x,n);
				for(int j=30;j>=0;j--)base[n][j] = bs[j],pos[n][j] = ps[j];	
			}else{
				scanf("%d %d",&l,&r);
				l=(l^las)%n+1;	r=(r^las)%n+1;
				if(l>r)swap(l,r);
				las = 0; 
				for(int j=30;j>=0;j--){
					if(pos[r][j]>=l&&(las^base[r][j])>las){
						las^=base[r][j];
					}
				}
				printf("%d\n",las);
			}
		}
	}
	return 0;
} 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章