Luogu-P4839 P brother's barrel (line segment tree + linear basis)

Question link
question meaning:

Gives nnn sets, each set has some number,mmm operations, there are two operations

1. 1. 1 . The firstkkk sets to join the numberxxx

2. 2. 2 . Query[l, r] [l,[l,r ] The exclusive OR of the set is the largest.

answer:

Seeing the interval query and modification, you can think of the line segment tree, and the XOR sum is the largest, you can think of the linear basis, then it is the line segment tree + linear basis.

Each time the number is added, it is updated to include the kkThe linear basis of the nodes of k sets.

The query operation is to take out the linear basis of all valid nodes again and put it in the array, and then calculate the linear basis again.

Code:

#include <bits/stdc++.h>
using namespace std;
const int MAXN=5e4+5;
typedef long long ll;
struct node
{
    
    
    int l,r;
    int val;
}node[MAXN<<2][31];
int dp[31];
void build(int l,int r,int num)
{
    
    
    for(int i=0;i<=30;i++){
    
    
        node[num][i].l=l;
        node[num][i].r=r;
        node[num][i].val=0;
    }
    if(l==r){
    
    
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,num<<1);
    build(mid+1,r,num<<1|1);
}
void push_up(int num,int x)
{
    
    
    for(int i=30;i>=0;i--){
    
    
        if((x>>i)&1){
    
    
            if(node[num][i].val){
    
    
                x^=node[num][i].val;
            }
            else{
    
    
                node[num][i].val=x;
                break;
            }
        }
    }
}
void updata(int pos,int x,int l,int r,int num){
    
    
    push_up(num,x);
    if(l==r){
    
    
        return;
    }
    int mid=(l+r)>>1;
    if(pos<=mid){
    
    
        updata(pos,x,l,mid,num<<1);
    }
    else{
    
    
        updata(pos,x,mid+1,r,num<<1|1);
    }
}
void query(int find_left,int find_right,int l,int r,int num)
{
    
    
    if(l>=find_left&&r<=find_right)
    {
    
    
        for(int i=30;i>=0;i--)
        {
    
    
            int x=node[num][i].val;
            if(!x) continue;
            for(int j=30;j>=0;j--){
    
    
                if((x>>j)&1){
    
    
                    if(!dp[j]){
    
    
                        dp[j]=x;
                        break;
                    }
                    else{
    
    
                        x^=dp[j];
                    }
                }
            }
        }
        return ;
    }
    int mid=(l+r)>>1;
    if(find_left<=mid) query(find_left,find_right,l,mid,num<<1);
    if(find_right>=mid+1) query(find_left,find_right,mid+1,r,num<<1|1);
}
int main(){
    
    
    int m,n;
    scanf("%d%d",&m,&n);
    build(1,n,1);
    int op;
    while(m--){
    
    
        scanf("%d",&op);
        if(op==1){
    
    
            int k,x;
            scanf("%d%d",&k,&x);
            updata(k,x,1,n,1);
        }
        else{
    
    
            int l,r;
            scanf("%d%d",&l,&r);
            memset(dp,0,sizeof dp);
            query(l,r,1,n,1);
            int ans=0;
            for(int i=30;i>=0;i--){
    
    
                if((ans^dp[i])>ans) ans^=dp[i];
            }
            printf("%d\n",ans);
        }
    }
}

Guess you like

Origin blog.csdn.net/weixin_45755679/article/details/114938369