题目背景
P哥在IOI取得了金牌,现在他开始找女朋友了!
题目描述
P哥现在有nn个桶,他们排成了一排,这些桶可以装下任意多个女朋友。每个女朋友有一个固定的颜值
P哥时不时地会找新女朋友,并把新找的女朋友丢进某个桶里面。我们用1\;k\;x1kx来表示P哥找了一个颜值为xx的女朋友,并且丢进了kk号桶里面
P哥每天晚上需要在特定的桶里面找一些女朋友观赏。我们用2\;l\;r2lr来表示P哥在ll号桶到rr号桶之间找女朋友。P哥希望观赏的女朋友颜值异或和尽可能大。
注意:P哥观赏完这些后会女朋友把它们物归原位
输入输出格式
输入格式:
第一行两个整数n,mn,m,依次表示P哥的操作次数、这组数据会涉及到的最大编号
接下来nn行,每行三个整数,表示操作。操作格式如题
输出格式:
对于每个观赏操作,输出P哥能观赏到的最大颜值异或和
输入输出样例
输入样例#1: 复制
5 3 1 1 2 1 2 3 1 3 4 2 1 2 2 1 3
输出样例#1: 复制
3 7
输入样例#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%的数据,满足n,m\leq 100n,m≤100
对于40%的数据,满足n,m\leq 1000n,m≤1000
另有20%的数据,所有询问满足l=1,r=ml=1,r=m
对于100%的数据,满足n,m\leq 5*10^4\;\;\;l\leq r\leq m\;\;\;k\leq m\;\;\;x\leq 2^{31}-1n,m≤5∗104l≤r≤mk≤mx≤231−1
题意:N个操作,第K个桶放一个X,查询L到R区间的桶任意数的异或最大值。
思路:线段树,每个节点维护区间的线性基,因为数据比较随机,所以判断线性基满了直接返回就能优化复杂度。
线性基:将一堆数(设最大值为MAX)压成log2(MAX)个数,可以求出它们异或的最大值,或者能否异或出某个数。
# include <bits/stdc++.h>
# define lson l,mid,id<<1
# define rson mid+1,r,id<<1|1
using namespace std;
typedef long long LL;
const int maxn = 5e4+30;
struct node{
int bit[32], len;
}a[maxn<<2];
void fun(node &x, int val){
if(x.len == 31) return;
for(int i=30; ~i; --i){
if(val&(1<<i)){
if(x.bit[i] == 0){
x.bit[i] = val;
++x.len;
break;
}
else val ^= x.bit[i];
}
}
}
void update(int pos, int val, int l, int r, int id){
fun(a[id], val);
if(l == r) return;
int mid = l+r>>1;
if(pos <= mid) update(pos, val, lson);
else update(pos, val, rson);
}
node Merge(node x, node y){
if(x.len == 31) return x;
if(y.len == 31) return y;
node tmp = x;
for(int i=30; ~i; --i)
if(y.bit[i])
fun(tmp, y.bit[i]);
return tmp;
}
node query(int L, int R, int l, int r, int id){
if(L<=l && R>=r) return a[id];
int mid = l+r>>1;
if(R <= mid) return query(L, R, lson);
else if(L > mid) return query(L, R, rson);
else return Merge(query(L, R, lson), query(L, R, rson));
}
int main(){
int n, m, op, x, y;
scanf("%d%d",&n,&m);
while(n--){
scanf("%d%d%d",&op,&x,&y);
if(op == 1) update(x, y, 1, m, 1);
else{
node tmp = query(x, y, 1, m, 1);
int ans = 0;
for(int i=30; ~i; --i)
if((ans^tmp.bit[i]) > ans) ans ^= tmp.bit[i];
printf("%d\n",ans);
}
}
return 0;
}