2019.7.26 多校一 1002 Operation(线性基+二维动态规划) [BJWC2011]元素(线性基+贪心)

推荐模板题
线性基模板
这题的题解写的挺好的大家可以康康

线性基呢
就是从几个数里
选出任意个数
使得它们异或起来得到的数最大

反正那个题解写的真挺好。。
我就不多讲具体原理

operation

这题讲的是一个在线的修改求线性基
里面还要decode一下。。。

那我们就用动态规划的思想
二维dp
线性基尽量取右边的数
然后运用pos数组检查是否在l到r之间
二维dp维护线性基
很巧妙

题解叫这个是上三角形态/线性基前缀和

#include<bits/stdc++.h>
using namespace std;
const int MAXN=500000+10;
int T,n,m,op,l,r,tmp,ans,a[MAXN],f[MAXN][32],pos[MAXN][32];
inline int Read() 
{
    int x=0,f=1; char ch=getchar(); 
    while (ch<'0'||ch>'9') {if (ch=='-') f=-f; ch=getchar();}
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
char s[30];
inline void writeln(int x)
{
	if (x<0) putchar('-'),x=-x; 
	if (!x) putchar('0'); else 
	{
	    int len=0;  
	    while (x) s[++len]=x%10+'0',x/=10;
	  	while (len) putchar(s[len--]);
	} 
	putchar('\n');
}
inline void Add(int i,int x)
{
	int k=i;
	for (int j=30;j>=0;--j) f[i][j]=f[i-1][j],pos[i][j]=pos[i-1][j];
	for (int j=30;j>=0;--j) if (x>>j)
	{ 
		if (!f[i][j]) 
		{
			f[i][j]=x;
			pos[i][j]=k;
			break; 
		}
		else 
		{
			if (k>pos[i][j]) 
			{
				tmp=k,k=pos[i][j],pos[i][j]=tmp;
				tmp=x,x=f[i][j],f[i][j]=tmp;
			}
            x^=f[i][j];
		}
	}
}
int main()
{
	//freopen("test.in","r",stdin);
	//freopen("test.out","w",stdout);
	T=Read();
	while (T--)
	{
		n=Read(),m=Read();
		for (int i=1;i<=n;++i) a[i]=Read(),Add(i,a[i]);
		ans=0;
	    while (m--)
	    {
	    	op=Read();
	    	if (op) a[++n]=Read()^ans,Add(n,a[n]);
			else
			{
				l=Read(),r=Read();
				l=(l^ans)%n+1,r=(r^ans)%n+1;
				if (l>r) swap(l,r);
                ans=0;
                for (int j=30;j>=0;--j) if((ans^f[r][j])>ans&&pos[r][j]>=l) ans^=f[r][j];
                writeln(ans);
			}
		}
		for (int i=1;i<=n;++i)
		  for (int j=30;j>=0;--j) f[i][j]=pos[i][j]=0;
	}
	return 0;
}

拓展练习
洛谷p4570
里面的题解里的线性基博客写的挺好的
线性基的性质概括了一下

这一题使用的线性基和本题类似
更简单一些
建议自己背一下写一下

注意long long位次最高到62
到63会很有意思
大家可以试试

#include<bits/stdc++.h>
#define ll long long
using namespace std;

ll ji[100];
int m[1005],pos[1005];
void add(int p,ll t){
	int k=p;
	for(int i=63;i>=0;i--){
		if(t>>(ll)i){
			if(!ji[i]){
				ji[i]=t;
				pos[i]=k;
				break;
			}else {
				if(m[k]>m[pos[i]]){
					swap(ji[i],t);
					swap(k,pos[i]);
				}
				t^=ji[i];
			}
			
		}
	}
}

int main(){
	int n,ans=0;
	ll t;
	scanf("%d",&n);
	memset(pos,-1,sizeof(pos));
	for(int i=0;i<n;i++){
		scanf("%lld%d",&t,&m[i]);
		add(i,t);
	}
	for(int i=0;i<=63;i++){
		if(pos[i]!=-1){
			ans+=m[pos[i]];
		}
		
	}
	printf("%d",ans);
	return 0;
}
发布了61 篇原创文章 · 获赞 8 · 访问量 2459

猜你喜欢

转载自blog.csdn.net/weixin_43982216/article/details/97398088