线段树+线性基

链接:P4839 P哥的桶 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

题意:对区间单点插入数据,求区间最大子集异或和。

题解:考虑线性基的合并,将另一个线性基的 log 个数拿出来合并入第一个线性基中,因为可以由另一个线性基合成出来的数,在把这个线性基合并进第一个线性基后,第一个线性基也可以合成出第二个线性基,再通过第二个线性基就可以合成那些数了。则可以用线段树来维护这些线性基的并。由于线性基合并复杂度为 log∗loglog*loglog∗log,线段树单点修改,区间查询复杂度为 qlognqlognqlogn,则整体复杂度为 q∗logn∗log2pq*logn*log^2pq∗logn∗log2p,q 为操作次数,n 为序列长度,p 为值域。

#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include<iostream>
#include<algorithm>
#include<cstring>using namespace std;
typedef long long ll;
const int maxn=5e4+5;int n,m,op,u,v,w;
struct node{int l,r,p[32];node():l(0),r(0){memset(p,0,sizeof(p));}
}t[maxn<<2];void insert(node&t,int x)
{for(int i=31;i>=0;i--){if(x>>i&1){if(!t.p[i]){t.p[i]=x; break;}x^=t.p[i];}}return;
}void pushup(int k)
{memcpy(t[k].p,t[k<<1].p,sizeof(t[k].p));for(int i=31;i>=0;i--){insert(t[k],t[k<<1|1].p[i]);}return;
}void build(int k,int l,int r)
{t[k].l=l,t[k].r=r;if(l==r)return;int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);return;
}void update(int k,int pos,int w)
{int x=t[k].l,y=t[k].r;if(x==y){insert(t[k],w); return;}int mid=x+y>>1;if(pos<=mid)update(k<<1,pos,w);else update(k<<1|1,pos,w);pushup(k); return;
}node query(int k,int l,int r)
{int x=t[k].l,y=t[k].r;if(l<=x&&y<=r)return t[k];int mid=x+y>>1,flag=0; node res;if(l<=mid)res=query(k<<1,l,r),flag=1;if(mid<r){if(!flag)res=query(k<<1|1,l,r);else {node q=query(k<<1|1,l,r); res.r=q.r;for(int i=31;i>=0;i--)insert(res,q.p[i]);}}return res;
}int main()
{ios::sync_with_stdio(false);cin.tie(0); cout.tie(0);cin>>n>>m,build(1,1,m);for(int i=1;i<=n;i++){cin>>op>>u>>v;if(op==1)update(1,u,v);else{node q=query(1,u,v); int ans=0;for(int i=31;i>=0;i--)ans=max(ans,ans^q.p[i]);cout<<ans<<"\n";}}return 0;
}

可以发现,这种合并确实是正确的,复杂度也是正确的。但可以考虑下,我们更新时自底层合并上高层,每次都会在原来线性基基础上加进来数,并不较少数字。所以可以并不需要合并,只需要在更新时对遍历到的点插入即可。

//#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
#include<iostream>
#include<algorithm>
#include<cstring>using namespace std;
typedef long long ll;
const int maxn=5e4+5;int n,m,op,u,v,w;
struct node{int l,r,p[32];node():l(0),r(0){memset(p,0,sizeof(p));}
}t[maxn<<2];void insert(node&t,int x)
{for(int i=31;i>=0;i--){if(x>>i&1){if(!t.p[i]){t.p[i]=x; break;}x^=t.p[i];}}return;
}void build(int k,int l,int r)
{t[k].l=l,t[k].r=r;if(l==r)return;int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);return;
}void update(int k,int pos,int w)
{int x=t[k].l,y=t[k].r; insert(t[k],w);if(x==y)return;int mid=x+y>>1;if(pos<=mid)update(k<<1,pos,w);else update(k<<1|1,pos,w);return;
}void query(node&q,int k,int l,int r)
{int x=t[k].l,y=t[k].r;if(l<=x&&y<=r){for(int i=31;i>=0;i--)insert(q,t[k].p[i]);return;}int mid=x+y>>1;if(l<=mid)query(q,k<<1,l,r);if(mid<r)query(q,k<<1|1,l,r);return;
}int main()
{ios::sync_with_stdio(false);cin.tie(0); cout.tie(0);cin>>n>>m,build(1,1,m);for(int i=1;i<=n;i++){cin>>op>>u>>v;if(op==1)update(1,u,v);else{node q; query(q,1,u,v); int ans=0;for(int i=31;i>=0;i--)ans=max(ans,ans^q.p[i]);cout<<ans<<"\n";}}return 0;
}

查询操作小优化:发现每次查询每个点时重新创建结构体太费时间了。则初始建立一个然后慢慢插入即可。

P 哥的桶(线段树+线性基)相关推荐

  1. 洛谷P4839 P哥的桶 线段树+线性基

    传送门 题意:N个操作,第K个桶放一个X,查询L到R区间的桶任意数的异或最大值. P哥时不时地会找新女朋友,并把新找的女朋友丢进某个桶里面.我们用 1 k x 来表示P哥找了一个颜值为x的女朋友,并且 ...

  2. 洛谷P4839 P哥的桶【线段树+线性基】

    题目描述 P哥现在有n个桶,他们排成了一排,这些桶可以装下任意多个女朋友.每个女朋友有一个固定的颜值 P哥时不时地会找新女朋友,并把新找的女朋友丢进某个桶里面.我们用1kx来表示P哥找了一个颜值为x的 ...

  3. P哥的桶(线段树+线性基)

    https://www.luogu.org/problem/P4839 题目: 有两个操作 1 a b  在a的位置添加b数值  (注意一个位置可以有多个值) 2 a b : 在 a到b的范围任取任意 ...

  4. [BZOJ4184]shallot 线段树+线性基

    链接 题意:给你每个数字出现的时间和消失的时间,求每个时刻最大异或和 题解 按照时间建立线段树,线段树每个节点开个vector存一下这个时间区间有哪些数,然后递归进入的时候加入线性基,开一个栈记录一下 ...

  5. 【NOIP2016】【桶/线段树合并】【树上差分】天天爱跑步

    [题目描述] [思路] 这是道好题呀.考虑把一条路径(u,v)拆成两条:从u到lca(u,v),从lca(u,v)到v.下面我们以向上的路径为例讨论做法.对于一条向上的路径,它对一个点x有贡献当且仅当 ...

  6. Luogu P5556 圣剑护符(线性基,树链剖分,线段树)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Problem 小L 和 小K 面前的圣剑由 nnn 块护符组成,分别编号为 1,2,-,n1,2,\ ...

  7. 2017年ICPC西安邀请赛A、XOR(线段树套线性基 + 思维)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 题目传送门 Problem 给你 nnn 和 nnn 个整数的数组 aaa,以及kkk和qqq,有 q ...

  8. 【线段树分治 线性基】luoguP3733 [HAOI2017]八纵八横

    不知道为什么bzoj没有HAOI2017 题目描述 Anihc国有n个城市,这n个城市从1~n编号,1号城市为首都.城市间初始时有m条高速公路,每条高速公路都有一个非负整数的经济影响因子,每条高速公路 ...

  9. P3292 [SCOI2016]幸运数字(树剖 + 线段树维护线性基)

    P3292 [SCOI2016]幸运数字 思路 如果这题是求x,yx, yx,y之间的距离显然我们可以通过树剖加线段树来写, 但是这里变成了求任意个数的异或最大值.如果给定区间我们显然可以通过线性基来 ...

  10. CF938G Shortest Path Queries(线性基/线段树分治/异或)

    CF938G Shortest Path Queries 支持加边删边和查询两点之间的异或最短路,我们可以使用线段树分治,然后利用线性基求解. 但是这里图可能不是联通的,所以查询两点之间的异或和需要边 ...

最新文章

  1. 涨知识了!网络原来是这样连接的
  2. python中文昵称-python3随机生成中文字符(随机生成两字或三字的名字)
  3. memcache 安装与简单使用
  4. Python按行输出文件内容具体解释及延伸
  5. poker java idea_JavaBasic学习笔记
  6. java str2date,java date类与string类实例代码分享
  7. 消费金融资金断流,银行抽贷、通道暂停,P2P离场
  8. 整理下STL algorithms(3)
  9. Spring Boot入门——多文件上传大小超限问题解决
  10. Drools 7.x Rate算法
  11. php类方法属性省略,第十课—类的属性和类的方法 2018年9月3日 20时00分
  12. MySQL JDBC URL中几个重要参数说明
  13. 字符串的模板 Manacher kmp ac自动机 后缀数组 后缀自动机
  14. 前阿里P10员工赵海平加入字节跳动,职级或为4+
  15. 使用微信公众号openid获取用户信息判断是否关注公众号
  16. 机器人操作臂运动学入门一--D-H参数标定
  17. 文件以及文件夹的管理
  18. js逆向--有道翻译
  19. 记录一下:老衲的py路程 mac下的tkinter小应用
  20. Pandas库——DataFrame入门

热门文章

  1. vue实现图片预加载的几种方式
  2. 微信支付接入-弹出支付框输入密码后一直在转圈,20s后提示:支付失败,请稍后再试
  3. TCPIP卷一(11):EIGRP的汇总、stub、leak-map参数
  4. dfuse Labs——展示 dfuse 的力量
  5. xgboost缺失值处理
  6. 华为鸿蒙系统平板电脑,华为5G鸿蒙系统平板电脑正式入网,搭载八核处理器麒麟9000芯片...
  7. matlab的syms无法在函数中使用_matlab syms什么意思_常见问题解析
  8. R数据分析:如何在R中使用mutate
  9. uniapp 苹果安全区配置
  10. STM8学习笔记1:CPU简介