P哥的桶(线段树+线性基)
https://www.luogu.org/problem/P4839
题目: 有两个操作 1 a b 在a的位置添加b数值 (注意一个位置可以有多个值) 2 a b : 在 a到b的范围任取任意的数值相异或,结果最大。
分析:用线段树去维护这个操作合并线性基的操作;时间复杂度O(nlogmlogx)
#include<bits/stdc++.h> using namespace std; const int maxn=1e6+10; struct LB{ int a[32]; void add(int x){ for(int i=31 ; i>=0 ; i--) { if(x&(1<<i)){ if(!a[i]){ a[i]=x; return ; } x^=a[i]; } } } void add(LB &n){ for(int i=31 ; i>=0 ; i--) if(n.a[i]) add(n.a[i]); } }p[maxn],ans; void update(int rt , int l , int r , int k , int x){ p[rt].add(x); if(l==r) return; int mid=(l+r)>>1; if(k<=mid) update(rt<<1,l,mid,k,x); else update(rt<<1|1,mid+1,r,k,x); } void query(int rt , int l , int r , int ql , int qr){ if(ql<=l&&qr>=r){ ans.add(p[rt]); return ; } int mid=(l+r)>>1; if(qr<=mid) query(rt<<1,l,mid,ql,qr); else if(mid<ql) query(rt<<1|1,mid+1,r,ql,qr); else query(rt<<1,l,mid,ql,mid),query(rt<<1|1,mid+1,r,ql,qr); } int main(){ int n,m;scanf("%d%d",&m,&n); for(int i=1 ; i<=m ; i++){ int op,a,b; scanf("%d%d%d",&op,&a,&b); if(op==1) update(1,1,n,a,b);///在a位置插b else { memset(ans.a,0,sizeof(ans.a)); query(1,1,n,a,b); int Max=0; for(int i=31 ; i>=0 ; i--) if((Max^(ans.a[i]))>Max) Max^=ans.a[i]; printf("%d\n",Max); } } return 0; }