51Nod1577 异或凑数 线性基 构造
国际惯例的题面:
异或凑出一个数,显然是线性基了。
显然我们能把区间[l,r]的数全都扔进一个线性基,然后试着插入w,如果能插入,则说明w不能被这些数线性表出,那么就要输出"NO"了。
然而怎么得到这个线性基?我们有两种很显然的暴力:线段树和单调莫队。然而亲测它们都不能AC......(不排除我写丑了)
考虑思考一下性质:如果我们能对于每个结束位置,用这个位置前面尽可能靠后的数构造出一个线性基,那么我们查询的时候是不是就能取出结束位置为r的线性基限制用的数出现位置不能早于l,然后直接查询就好了呢?(这种思想在Bzoj3514: Codechef MARCH14 GERALD07加强版)中也用到过。
好,如果这样做的话,怎么从结束位置为i-1的线性基得到结束位置为i的线性基呢?
我们可以把结束位置为i-1的线性基拆了,然后贪心按照出现位置从大到小插入,正确性显然,复杂度O(900n)。
查询的时候怎么办?我们把结束位置为r的线性基中出现位置>l的数拆出来,插入一个新线性基,进行查询,复杂度O(900q)。
非常不幸的是,这样仍然不能AC。虽然我已经千方百计卡常数了。
我们现在在维护出现最晚的线性无关的30个数,考虑我们维护序列最大的30个数怎么维护。
只有30个数,我们再写个堆(priority_queue?假装你是Pascal党好了)什么的显然不必要了。直接在插入的时候从大到小进行一轮冒泡排序,用当前的大数替换小数就好。
对于这个线性基,我们也能这样做。
我们从高位向低位扫描这个线性基,如果我们当前的数能被放入某个位置的话,如果这个位置为空,则直接放入;否则比较出现位置,如果当前数出现较为靠后的话,则把当前数和这个位置的数swap一下,然后从下一位继续进行插入。
然后我们会发现这样构造的线性基还会有另一个更好的性质:高位上的数出现尽量靠后。
查询的时候,从高位到低位进行查询。如果凑出w需要高位的某个数而这个数出现位置<l,那么这一位无论如何都消不掉了,直接输出'NO'即可。
这样我们就把复杂度优化为了O(30n+30q),能够轻松AC。
暴力线段树代码:
#pragma GCC optimize("Ofast,no-stack-protector")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#include<cstdio>
#include<cstring>
#include<cctype>
#define bool unsigned char
typedef unsigned int ui;
const int maxn=,maxl=; ui in[maxn>>],bit[maxl]; struct LinearBase {
ui dat[maxl];
__inline const ui& operator [] (const ui &x) const { return dat[x]; }
__inline bool insert(ui x) {
for(ui i=;~i;i--) if( x & bit[i] ) {
if( !dat[i] ) return dat[i] = x , ;
else x ^= dat[i];
}
return ;
}
__inline void merge(const LinearBase &r) {
for(ui i=;~i;i--) if( r[i] ) insert(r[i]);
}
__inline void reset() {
memset(dat,,sizeof(dat));
}
}ans; struct SegmentTree {
LinearBase dat[maxn];
#define lson(pos) (pos<<1)
#define rson(pos) (pos<<1|1)
__inline void build(ui pos,ui l,ui r) {
if( l == r ) return void(dat[pos].insert(in[l]));
const ui mid = ( l + r ) >> ;
build(lson(pos),l,mid) , build(rson(pos),mid+,r);
dat[pos] = dat[lson(pos)] , dat[pos].merge(dat[rson(pos)]);
}
__inline void query(ui pos,ui l,ui r,const ui &ll,const ui &rr) {
if( ll <= l && r <= rr ) return ans.merge(dat[pos]);
const ui mid = ( l + r ) >> ;
if( ll <= mid ) query(lson(pos),l,mid,ll,rr);
if( mid < rr ) query(rson(pos),mid+,r,ll,rr);
}
}sgt; __inline unsigned char nextchar() {
static const ui BS = << ;
static unsigned char buf[BS],*st,*ed;
if( st == ed ) ed = buf + fread(st=buf,,BS,stdin);
return st == ed ? : *st++;
}
__inline ui getint() {
ui ret = ;
unsigned char ch;
while( !isdigit(ch=nextchar()) ) ;
do ret=ret*+ch-''; while( isdigit(ch=nextchar()) );
return ret;
} int main() {
static ui n,q,l,r,w;
n = getint();
for(ui *st=in+,*ed=st+n;st!=ed;*st++=getint());
for(ui i=;i<;i++) bit[i] = << i;
sgt.build(,,n) , q = getint();
while(q--) {
l = getint() , r = getint() , w = getint() , ans.reset();
sgt.query(,,n,l,r);
puts(ans.insert(w)?"NO":"YES");
}
return ;
}
暴力重构线性基:
#pragma GCC optimize("Ofast")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
#define debug cout
using namespace std;
const int maxn=5e5+1e2,maxl=;
const int inf=0x3f3f3f3f; int in[maxn],seq[maxl+],sql; struct LinearBase {
int dat[maxl],bel[maxl];
inline bool insert(int id,int val) {
for(int i=;~i;i--) if( val & ( << i ) ) {
if( !dat[i] ) {
dat[i] = val , bel[i] = id;
return ;
} else val ^= dat[i];
}
return ;
}
inline int findremove(int val) {
int mx = inf;
for(int i=;~i;i--) if( bel[i] && ( val & ( << i ) ) ) mx = min( mx , bel[i] );
return mx;
}
inline void output(int lim) {
for(int i=;~i;i--) if( bel[i] >= lim ) seq[++sql] = bel[i];
}
inline bool insert(int val) {
for(int i=;~i;i--) if( val & ( << i ) ) {
if( !dat[i] ) return dat[i] = val , ;
else val ^= dat[i];
}
return ;
}
inline void reset() {
memset(dat,,sizeof(dat)) , memset(bel,,sizeof(bel));
}
}lb[maxn],tp; inline char nextchar() {
static const int BS = << ;
static char buf[BS],*st,*ed;
if( st == ed ) ed = buf + fread(st=buf,,BS,stdin);
return st == ed ? : *st++;
}
inline int getint() {
int ret = ;
char ch;
while( !isdigit(ch=nextchar()) ) ;
do ret=ret*+ch-''; while( isdigit(ch=nextchar()) );
return ret;
} int main() {
static int n,q,l,r,w;
n = getint();
for(int i=;i<=n;i++) {
lb[i] = lb[i-];
if( !lb[i].insert(i,in[i]=getint()) ) {
sql = , lb[i-].output() , lb[i].reset();
lb[i].insert(i,in[i]) , std::sort(seq+,seq++sql);
for(int j=sql;j;j--) lb[i].insert(seq[j],in[seq[j]]);
}
}
q = getint();
while(q--) {
l = getint() , r = getint() , w = getint();
sql = , lb[r].output(l) , tp.reset();
for(int i=;i<=sql;i++) tp.insert(in[seq[i]]);
puts(tp.insert(w)?"NO":"YES");
}
return ;
}
正解代码:
#pragma GCC optimize("Ofast")
#include<cstdio>
#include<algorithm>
#include<cctype>
const int maxn=5e5+1e2,maxl=;
const int inf=0x3f3f3f3f; int in[maxn],seq[maxl+],sql;
bool vis[maxn]; struct LinearBase {
int dat[maxl],bel[maxl];
inline void insert(int id,int val) {
for(int i=;~i;i--) if( val & ( << i ) ) {
if( !dat[i] ) {
dat[i] = val , bel[i] = id;
return;
} else {
if( bel[i] < id ) std::swap(bel[i],id) , std::swap(val,dat[i]);
val ^= dat[i];
}
}
}
inline bool query(int val,int lim) {
for(int i=;~i;i--) if( val & ( << i ) ) {
if( !dat[i] || bel[i] < lim ) return ;
val ^= dat[i];
}
return ;
}
}lb[maxn],tp; inline char nextchar() {
static const int BS = << ;
static char buf[BS],*st,*ed;
if( st == ed ) ed = buf + fread(st=buf,,BS,stdin);
return st == ed ? : *st++;
}
inline int getint() {
int ret = ;
char ch;
while( !isdigit(ch=nextchar()) ) ;
do ret=ret*+ch-''; while( isdigit(ch=nextchar()) );
return ret;
} int main() {
static int n,q,l,r,w;
n = getint();
for(int i=;i<=n;i++) lb[i] = lb[i-] , lb[i].insert(i,in[i]=getint());
q = getint();
while(q--) {
l = getint() , r = getint() , w = getint(), puts(lb[r].query(w,l)?"NO":"YES");
}
return ;
}
明けの星が
启明的星辰
光を見せた
洒下丝丝光芒
よわい よわい
微微地 微微地
こころに降りそそぐ
纷纷洒落到我心房
でも時は
可有的时候
おなじ想いだけを
如果能够继续
あ…描き続ければ
描绘同样的思念…
誰も知らず
谁也不知道
日が射すまでに
直到太阳升起
そっと そっと
静静地 静静地
予感を感じてた
我感觉到一丝预感
こころが感じてた
我的心 有了一丝预感
51Nod1577 异或凑数 线性基 构造的更多相关文章
- 51Nod1577 异或凑数 线性基
原文链接https://www.cnblogs.com/zhouzhendong/p/51Nod1577.html 题意 给定一个长度为 n 的序列. 有 m 组询问,每一组询问给出 L,R,k ,询 ...
- 51nod 1577 异或凑数 线性基的妙用
\(OTZgengyf\)..当场被吊打\(QwQ\) 思路:线性基 提交:\(3\)次 错因:往里面加数时\(tmp.p\)与\(i\)区分不清(还是我太菜了) 题解: 我们对每个位置的线性基如此操 ...
- [51nod1577]异或凑数
题目 点这里看题目. 分析 以下设\(k=\lfloor\log_2(\max a)\rfloor\). 关于异或凑数的问题自然可以用线性基处理,即如果可以插入到线性基,就说明无法凑出这个 ...
- 【XSY2701】异或图 线性基 容斥原理
题目描述 定义两个图\(G_1\)与\(G_2\)的异或图为一个图\(G\),其中图\(G\)的每条边在\(G_1\)与\(G_2\)中出现次数和为\(1\). 给你\(m\)个图,问你这\(m\)个 ...
- BZOJ 4671 异或图 | 线性基 容斥 DFS
题面 Description 定义两个结点数相同的图 G1 与图 G2 的异或为一个新的图 G, 其中如果 (u, v) 在 G1 与 G2 中的出现次数之和为 1, 那么边 (u, v) 在 G 中 ...
- 【loj114】k大异或和 线性基+特判
题目描述 给由 $n$ 个数组成的一个可重集 $S$ ,每次给定一个数 $k$ ,求一个集合 $T⊆S$ ,使得集合 $T$ 在 $S$ 的所有非空子集的不同的异或和中,其异或和 $T_1 ...
- LOJ.114.K大异或和(线性基)
题目链接 如何求线性基中第K小的异或和?好像不太好做. 如果我们在线性基内部Xor一下,使得从高到低位枚举时,选base[i]一定比不选base[i]大(存在base[i]). 这可以重构一下线性基, ...
- bzoj 2115 [Wc2011] Xor 路径最大异或和 线性基
题目链接 题意 给定一个 \(n(n\le 50000)\) 个点 \(m(m\le 100000)\) 条边的无向图,每条边上有一个权值.请你求一条从 \(1\)到\(n\)的路径,使得路径上的边的 ...
- LOJ #113. 最大异或和 (线性基)
题目链接:#113. 最大异或和 题目描述 这是一道模板题. 给由 \(n\) 个数组成的一个可重集 \(S\),每次给定一个数 \(k\),求一个集合 \(T \subseteq S\),使得集合 ...
随机推荐
- Jetson tk1 刷机教程
前期准备: 1. Jetson TK1开发板. 2. 安装有ubuntu系统的PC(或者ubuntu虚拟机)切记:不管是PC还是虚拟机,务必确保有大于5G的存储空间,之后安装过程会作详细解释. 3 ...
- 【Python】多线程-线程池使用
1.学习目标 线程池使用 2.编程思路 2.1 代码原理 线程池是预先创建线程的一种技术.线程池在还没有任务到来之前,创建一定数量的线程,放入空闲队列中.这些线程都是处于睡眠状态,即均为启动,不消耗 ...
- PhantomJSのメモいろいろ
提供されるモジュール群は5つ phantom: そのもの FileSystem: ファイルに出力したり.依存ファイルの存在確認したり System: コマンドラインから引数取りたいなら WebPage ...
- 018_mac写权限的问题
一. 有时候运行一些软件的时候,操作系统下的文件没有写权限.我在使用"HostAdmin App"时碰到了这个问题,google的链接供参考:https://code.google ...
- 015_NGINX作为WebSocket Proxy的设置
产研那边有通过nginx代理进行长连接的需求,咱们都知道默认nginx只支持短连接的,使用长连接需要单独配置 一. websocket协议提供创建一种支持在server和client之前双向通信的we ...
- selenium捕捉视频
捕捉视频 有时候我们未必能够分析故障只需用日志文件或截图的帮助.有时捕获完整的执行视频帮助.让我们了解如何捕捉视频. 我们将利用Monte媒体库的执行相同. 配置 第1步:导航到URL - http: ...
- js学习、备忘
字符串使用单引号’abc’.(双引号也行.推荐:html→双引号,js→单引号)===严格等于.!==严格不等于if(x) 当x为undefined.null和0的时候都为false:需注意当x为0 ...
- vue系列之vue-resource
vue-resource是Vue.js的一款插件,它可以通过XMLHttpRequest或JSONP发起请求并处理响应.也就是说,$.ajax能做的事情,vue-resource插件一样也能做到,而且 ...
- hdu1255扫描线计算覆盖两次面积
总体来说也是个模板题,但是要开两个线段树来保存被覆盖一次,两次的面积 #include<iostream> #include<cstring> #include<cstd ...
- python 全栈开发,Day85(Git补充,随机生成图片验证码)
昨日内容回顾 第一部分:django相关 1.django请求生命周期 1. 当用户在浏览器中输入url时,浏览器会生成请求头和请求体发给服务端 请求头和请求体中会包含浏览器的动作(action),这 ...