zoukankan      html  css  js  c++  java
  • [Cometoj#3 D]可爱的菜菜子_线段树_差分_线性基

    可爱的菜菜子

    题目链接https://cometoj.com/contest/38/problem/D?problem_id=1543

    数据范围:略。


    题解

    首先,如果第一个操作是单点修改,我们就只需要用线段树维护区间线性基即可。

    但是,第一个操作是区间异或,这就很难受了。

    区间操作可以怎么转化成单点?差分呗。

    将原序列异或差分之后,确实修改变成了单点修改。

    查询是否有影响?其实是没有影响的因为相当于整个一个区间的每个数异或上同一个数(前$l - 1$个数的异或和),线性基不受影响。

    代码

    #include<bits/stdc++.h>
    #define mms(a,n) memset(a,0,sizeof((a)[0])*(n))
    #define mmp(a,b,n) memcpy(a,b,sizeof((b)[0])*(n))
    #define lowbit(x) ((x)&-(x))
    #define pb push_back
    #define fi first
    #define se second
    #define debug(...) fprintf(stderr,__VA_ARGS__)
    #define lowbit(x) ((x)&-(x))
    #define fo(i,l,r) for(register int i=l,_lim_=r;i<=_lim_;i++)
    #define fd(i,r,l) for(register int i=r,_lim_=l;i>=_lim_;i--)
    
    using namespace std;
    typedef unsigned long long ull;
    typedef long long ll;
    typedef pair<int,int> pi;
    typedef double db;
    typedef long double ldb;
    
    namespace io{
    	const int L=(1<<21)+1;
    	char ibuf[L],*iS,*iT,obuf[L],*oS=obuf,*oT=obuf+L-1,c,st[55];int f,tp;
    	#ifdef FREOPEN
    		#define gc() getchar()
    	#else
    		#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,L,stdin),(iS==iT?EOF:*iS++)):*iS++)
    	#endif
    	inline void flush(){fwrite(obuf,1,oS-obuf,stdout);oS=obuf;}
    	inline void putc(char x){*oS++=x;if(oS==oT)flush();}
    	template<class I>
    	inline void gi(I&x){
    		for(f=1,c=gc();c<'0'||c>'9';c=gc())if(c=='-')f=-1;
    		for(x=0;c<='9'&&c>='0';c=gc())x=x*10+(c&15);x*=f;
    	}
    	template<class I>
    	inline void print(I x){
    		if(!x)putc('0');if(x<0)putc('-'),x=-x;
    		while(x)st[++tp]=x%10+'0',x/=10;
    		while(tp)putc(st[tp--]);
    	}
    	inline void gs(char*s,int&l){
    		for(c=gc();c!='_'&&(c<'a'||c>'z');c=gc());
    		for(l=0;c=='_'||c<='z'&&c>='a';c=gc())s[l++]=c;
    	}
    };
    using io::putc;
    using io::gi;
    using io::gs;
    using io::print;
    
    const int N=200005,M=32,L=525005;
    
    int n,q,a[N],mx;
    struct LinearBase{
    	int a[M],m;
    	int find(int k){
    		for(int i=1;i<=m;i++)if((k^a[i])<k)k^=a[i];
    		return k;
    	}
        int query(int x) {
            for(int i = 1; i <= m; ++i) if((x^a[i])>x)
                x ^= a[i];
            return x;
        }
    
    	void ext(int k){
    		if(mx>>m){
    			if(k=find(k)){
    				int j=1;
    				while(k<=a[j])j++;
    				++m;for(int i=m;i>j;i--)a[i]=a[i-1];
    				a[j]=k;
    				for(int i=1;i<j;i++)if((k^a[i])<a[i])a[i]^=k;
    			}
    		}	
    	}
    	friend LinearBase operator+(const LinearBase&a,const LinearBase&b){
    		if((1ll<<a.m)>mx)return a;if((1ll<<b.m)>mx)return b;
    		LinearBase ret=a;
    		for(int i=1;i<=b.m;i++)ret.ext(b.a[i]);
    		return ret;
    	}
    	void clear(){while(m)a[m--]=0;}
    }seg[L],ans;
    
    void build(int x,int l,int r){
    	if(l==r){
    		seg[x].ext(a[l]);
    		return;
    	}
    	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
    	build(ls,l,mid);build(rs,mid+1,r);
    	seg[x]=seg[ls]+seg[rs];
    }
    
    void modify(int x,int l,int r,int p,int k){
    	if(l==r){
    		seg[x].a[1]^=k;
    		mx=max(mx,seg[x].a[1]);
    		if(!seg[x].a[1])seg[x].m=0;else seg[x].m=1;
    		return;
    	}
    	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
    	if(p<=mid)modify(ls,l,mid,p,k);
    	else modify(rs,mid+1,r,p,k);
    	seg[x]=seg[ls]+seg[rs];
    }
    void modify(int x,int l,int r,int p,int q,int k){
    	if(l==r){
    		seg[x].a[1]^=k;
    		mx=max(mx,seg[x].a[1]);
    		if(!seg[x].a[1])seg[x].m=0;else seg[x].m=1;
    		return;
    	}
    	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
    	if(q<=mid)modify(ls,l,mid,p,q,k);
    	else if(p>mid)modify(rs,mid+1,r,p,q,k);
    	else modify(ls,l,mid,p,k),modify(rs,mid+1,r,q,k);
    	seg[x]=seg[ls]+seg[rs];
    }
    
    LinearBase query(int x,int l,int r,int s,int t){
    	if(l==s&&r==t)return seg[x];
    	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
    	if(t<=mid)return query(ls,l,mid,s,t);
    	if(s>mid)return query(rs,mid+1,r,s,t);
    	if(t-mid>=mid-s+1){
    		LinearBase w=query(rs,mid+1,r,mid+1,t);
    		if((1ll<<w.m)>mx)return w;
    		return w+query(ls,l,mid,s,mid);
    	}
    	LinearBase w=query(ls,l,mid,s,mid);
    	if((1ll<<w.m)>mx)return w;
    	return w+query(rs,mid+1,r,mid+1,t);
    }
    
    int sum[N];
    void add(int x,int u){while(x<=n)sum[x]^=u,x+=lowbit(x);}
    int ask(int x){int r=0;while(x)r^=sum[x],x-=lowbit(x);return r;} 
    
    int main(){
    	scanf("%d%d", &n, &q);
    	for(int i=1,s=0;i<=n;i++) {
    		scanf("%d", a + i);
    		add(i, a[i]);
    		add(i + 1, a[i]);
    	}
    	for(int i=n;i>=1;i--)mx=max(mx,a[i]^=a[i-1]);
    	build(1,1,n);
    	for(int i=1,op,l,r,k;i<=q;i++){
    		scanf("%d%d%d%d", &op, &l, &r, &k);
    		if(op==1){
    			if(r<n)modify(1,1,n,l,r+1,k);else modify(1,1,n,l,k);
    			add(l,k);add(r+1,k);
    		}else{
    			if(l<r)ans=query(1,1,n,l+1,r);else ans.clear();
    			ans.ext(ask(l));
    			printf("%d
    ", ans.query(k));
    		}
    	}
    	return 0;
    }
  • 相关阅读:
    自我介绍
    第一学期第一周学习总结
    2020-2021-1 20201332杨赛 《信息安全专业导论》第一周学习总结
    自我介绍
    2020-2021-1 20201307 《信息安全专业导论》第2周学习总结
    师生关系
    教材快速浏览
    2020-2021-1 20201307 《信息安全专业导论》第一周学习总结
    自我介绍
    20201319《信息安全导论》第一周学习总结
  • 原文地址:https://www.cnblogs.com/ShuraK/p/11726575.html
Copyright © 2011-2022 走看看