P 哥的桶
题目描述
P 哥现在有 n n n 个桶,它们排成了一排,这些桶可以装下任意多个球。每个球有一个固定的价值。
P 哥时不时地会找新球,并把新找的球丢进某个桶里面。我们用 1 k x 1\;k\;x 1kx 来表示 P 哥找了一个价值为 x x x 的球,并且丢进了 k k k 号桶里面。
P 哥每次会在特定的桶里面拿出一些球。我们用 2 l r 2\;l\;r 2lr 来表示 P 哥在 l l l 号桶到 r r r 号桶之间拿球。P 哥希望拿出来的球的价值异或和尽可能大。
注意:P 哥拿出这些球后会把它们物归原位。
输入格式
第一行两个整数 n , m n, m n,m,依次表示 P 哥的操作次数、这组数据会涉及到的最大编号。
接下来 n n n 行,每行三个整数,表示操作。操作格式如题。
输出格式
对于每个 2 操作,输出 P 哥拿出的球的最大价值异或和。
样例 #1
样例输入 #1
5 3
1 1 2
1 2 3
1 3 4
2 1 2
2 1 3
样例输出 #1
3
7
样例 #2
样例输入 #2
11 10
2 6 9
1 9 1523456696
1 1 1818963290
2 6 7
1 1 102229226
2 1 9
2 3 7
1 5 34895532
1 1 1652480680
1 1 1477666032
2 1 10
样例输出 #2
0
0
1818963290
0
1857442578
提示
对于 20 % 20 \% 20% 的数据,满足 n , m ≤ 100 n,m\leq 100 n,m≤100。
对于 40 % 40 \% 40% 的数据,满足 n , m ≤ 1000 n,m\leq 1000 n,m≤1000。
另有 20 % 20 \% 20% 的数据,所有询问满足 l = 1 l=1 l=1, r = m r=m r=m。
对于 100 % 100 \% 100% 的数据,满足 1 ≤ n , m ≤ 5 × 1 0 4 1 \le n, m \leq 5 \times 10^4 1≤n,m≤5×104, 1 ≤ l ≤ r ≤ m 1 \le l\leq r\leq m 1≤l≤r≤m, 1 ≤ k ≤ m 1 \le k \leq m 1≤k≤m, 0 ≤ x ≤ 2 31 − 1 0 \le x \leq 2^{31}-1 0≤x≤231−1。
#include <bits/stdc++.h>
using namespace std;
struct lb
{
int a[32];
void insert(int x)
{
for(int i=31;i>=0;--i)
if(x&(1<<i))
if(a[i])x^=a[i];
else
{
a[i]=x;
return;
}
}
void insert(lb &n)
{
for(int i=31;i>=0;--i)
if(n.a[i])insert(n.a[i]);
}
}p[200001];
void insert(int o,int l,int r,int k,int x)
{
p[o].insert(x);
if(l==r)return;
int mid=(l+r)>>1;
if(k<=mid)
insert(o<<1,l,mid,k,x);
else
insert(o<<1|1,mid+1,r,k,x);
}
lb ans;
void query(int o,int l,int r,int ql,int qr)
{
if(ql<=l && qr>=r){ans.insert(p[o]);return;}
int mid=(l+r)>>1;
if(qr<=mid)query(o<<1,l,mid,ql,qr);
else if(mid<ql)query(o<<1|1,mid+1,r,ql,qr);
else query(o<<1,l,mid,ql,mid),query(o<<1|1,mid+1,r,mid+1,qr);
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
{
int op,a,b;
scanf("%d%d%d",&op,&a,&b);
if(op==1)insert(1,1,m,a,b);
else
{
memset(ans.a,0,sizeof(ans.a));
query(1,1,m,a,b);
int maxn=0;
for(int i=31;i>=0;--i)
if((maxn^(ans.a[i]))>maxn)
maxn^=ans.a[i];
printf("%d\n",maxn);
}
}
}