标签:lim LL rfor 笔记 查询 异或 ans 线性
用处
- 快速查询一个数是否可以被一堆数异或出来
- 快速查询一堆数可以异或出来的最大 / 最小值
- 快速查询一堆数可以异或出来的第 \(k\) 大值
性质
- 原数列里的任何一个数都可以通过线性基里的数异或表示出来
- 线性基里任意一个子集的异或和都不为 \(0\)
- 一个数列可能有多个线性基,但是线性基里数的数量一定唯一,而且是满足性质一的基础上最少的。
实现
构造
void insert(LL x){
rfor(i, lim, 0) if(x & (1LL << i)){
if(a[i]) x ^= a[i];
else{ a[i] = x; break; }
}
}
查询一个元素是否可以被异或出来
bool check(LL x) {
rfor(i, lim, 0) if(x & (1LL << i)) x ^= a[i];
return x == 0;
}
查询异或最大值
按位贪心.
LL askmax() {
LL ans = 0;
rfor(i, lim, 0) if(ans < (ans ^ a[i])) ans ^= a[i];
return ans;
}
查询异或最小值
一般来说就是线性基里的最小元素,特判 \(0\).
LL askmin() {
if(zero) return 0;
lfor(i, 0, lim) if(a[i]) return a[i];
}
查询异或第 \(k\) 小
重建线性基,使得不同位尽量不相互影响。
void rebuild() {
rfor(i, lim, 0) rfor(j, i - 1, 0) if(a[i] & (1LL << j)) a[i] ^= a[j];
lfor(i, 0, lim) if(a[i]) p[++cnt] = a[i];
}
类似树状数组二分第 \(k\) 小,同样特判 \(0\).
LL kth(int k) {
LL ans=0;
rfor(i, lim, 0) if(k & (1LL << i)) ans ^= p[i];
return ans;
}
查询排名
与查询第 \(k\) 小类似.
int rank(LL x) {
LL ans = 0;
rfor(i, cnt - 1, 0) if(x >= p[i]) ans += (1LL << i), x ^= p[i];
return ans + zero;
}
题目
从 \(1-n\) 的最大XOR和路径可以看作任意一条从 \(1-n\) 的路径异或上若干个环。
分析出答案的补集就是线性基。
标签:lim,LL,rfor,笔记,查询,异或,ans,线性 来源: https://www.cnblogs.com/Callis/p/15900745.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。