P12827 「DLESS-2」XOR and Even 题解

AI 做不出这种题吗,挺有道理的。

最开始做这个题的时候,我就想过如果区间异或上一个数时,如果简单地将线性基内的元素全部异或,那么只有偶数个元素的集合搞出来是正确的,所以直接做是不可行的,但在这个题上却刚刚好。

先用带时间戳的线性基把询问区间的线性基搞出来(要离线扫描线)。

对于第二种询问,我们将线性基中每一个数都异或 \(2^{30}\)\(x\) 也异或上 \(2^{30}\),这样因为要贪心取最大值,所以最后的方案一定是取了偶数个数。否则答案不带 \(2^{30}\) 一定更小。

对于第一种询问,我们同样地做,这样奇数个数的方案异或出来的值带有 \(2^{30} > x\),所以一定不合法,求答案只需按位贪心,假设前面几位都顶到了上界,此时异或出来的值是确定的,然后分讨计算即可。最后答案要乘上 \(2^{r-l+1-cnt}\)\(cnt\) 是线性基的元素个数)。

分讨的部分可以看看代码。

const int V=60;
struct Linear_Basis{
	int b[V+5],tm[V+5];
	inline void Insert(int x,int t,int st){
		for(int i=st;i>=0;i--){
			if((x>>i)&1){
				if(b[i]){
					if(tm[i]<t){
						Insert(x^b[i],tm[i],i-1);
						b[i]=x;tm[i]=t;
						break;
					}
					else x^=b[i];
				}else{
					b[i]=x;tm[i]=t;
					break;
				}
			}
		}
	}
	inline int Query(int x,int v){
		int now=v;
		for(int i=30;i>=0;i--)
			if(tm[i]>=x&&!(now>>i&1))
				now^=b[i];
		return now;
	}
    int c[60];
    inline int Get(int l,int r,int x){
        int cnt=0,ans=0,now=0;
        c[0]=(b[0]!=0)&&tm[0]>=l;
        for(int i=1;i<=30;i++)c[i]=c[i-1]+((b[i]!=0)&&tm[i]>=l);
        for(int i=30;i>=0;i--)if(tm[i]>=l&&b[i])++cnt;
        for(int i=30;;i--){
            if(i==-1){
                if(now<=x)Add(ans,1);
                break;
            }
            if(x>>i&1){
                if((now>>i&1)&&(b[i]&&tm[i]>=l))Add(ans,i?m2[c[i-1]]:1);
                if(!(now>>i&1)){
                    if(b[i]&&tm[i]>=l){
                        now^=b[i];
                        if(i)Add(ans,m2[c[i-1]]);
                        else Add(ans,1);
                    }else{
                        if(i)Add(ans,m2[c[i-1]]);
                        else Add(ans,1);
                        break;
                    }
                }
            }else{
                if(now>>i&1){
                    if(!b[i]||tm[i]<l)break;
                    else if(tm[i]>=l)now^=b[i];
                }
            }
        }
        ans=1ll*ans*m2[r-l+1-cnt]%mod;
        return ans;
    }
    inline void Clear(){
        memset(b,0,sizeof b);
        memset(tm,0,sizeof tm);
    }
}LB;
inline void Solve(){
    rd(n,q);
    for(int i=1;i<=n;i++)rd(a[i]);
    for(int i=1;i<=q;i++){
        int op,l,r,x;rd(op,l,r,x);
        vec[r].emplace_back(op,l,x,i);
    }
    LB.Clear();
    for(int i=1;i<=n;i++){
        LB.Insert(a[i]^(1<<30),i,30);
        for(auto[op,l,x,id]:vec[i]){
            if(op==1){
                ans[id]=LB.Query(l,x^(1<<30))^(1<<30);
            }else{
                ans[id]=LB.Get(l,i,x);
            }
        }
    }
    for(int i=1;i<=n;i++)vec[i].clear();
    for(int i=1;i<=q;i++)printf("%d\n",ans[i]);
}
signed main(){
    m2[0]=1;
    for(int i=1;i<=500000;i++)m2[i]=m2[i-1]*2%mod;
    rd(T);
    while(T--)Solve();
    return 0;
}
posted @ 2025-06-14 21:36  KIreteria  阅读(22)  评论(0)    收藏  举报