P 哥的桶(线段树+线性基)
线段树+线性基
链接: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 哥的桶(线段树+线性基)相关推荐
- 洛谷P4839 P哥的桶 线段树+线性基
传送门 题意:N个操作,第K个桶放一个X,查询L到R区间的桶任意数的异或最大值. P哥时不时地会找新女朋友,并把新找的女朋友丢进某个桶里面.我们用 1 k x 来表示P哥找了一个颜值为x的女朋友,并且 ...
- 洛谷P4839 P哥的桶【线段树+线性基】
题目描述 P哥现在有n个桶,他们排成了一排,这些桶可以装下任意多个女朋友.每个女朋友有一个固定的颜值 P哥时不时地会找新女朋友,并把新找的女朋友丢进某个桶里面.我们用1kx来表示P哥找了一个颜值为x的 ...
- P哥的桶(线段树+线性基)
https://www.luogu.org/problem/P4839 题目: 有两个操作 1 a b 在a的位置添加b数值 (注意一个位置可以有多个值) 2 a b : 在 a到b的范围任取任意 ...
- [BZOJ4184]shallot 线段树+线性基
链接 题意:给你每个数字出现的时间和消失的时间,求每个时刻最大异或和 题解 按照时间建立线段树,线段树每个节点开个vector存一下这个时间区间有哪些数,然后递归进入的时候加入线性基,开一个栈记录一下 ...
- 【NOIP2016】【桶/线段树合并】【树上差分】天天爱跑步
[题目描述] [思路] 这是道好题呀.考虑把一条路径(u,v)拆成两条:从u到lca(u,v),从lca(u,v)到v.下面我们以向上的路径为例讨论做法.对于一条向上的路径,它对一个点x有贡献当且仅当 ...
- Luogu P5556 圣剑护符(线性基,树链剖分,线段树)
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Problem 小L 和 小K 面前的圣剑由 nnn 块护符组成,分别编号为 1,2,-,n1,2,\ ...
- 2017年ICPC西安邀请赛A、XOR(线段树套线性基 + 思维)
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 题目传送门 Problem 给你 nnn 和 nnn 个整数的数组 aaa,以及kkk和qqq,有 q ...
- 【线段树分治 线性基】luoguP3733 [HAOI2017]八纵八横
不知道为什么bzoj没有HAOI2017 题目描述 Anihc国有n个城市,这n个城市从1~n编号,1号城市为首都.城市间初始时有m条高速公路,每条高速公路都有一个非负整数的经济影响因子,每条高速公路 ...
- P3292 [SCOI2016]幸运数字(树剖 + 线段树维护线性基)
P3292 [SCOI2016]幸运数字 思路 如果这题是求x,yx, yx,y之间的距离显然我们可以通过树剖加线段树来写, 但是这里变成了求任意个数的异或最大值.如果给定区间我们显然可以通过线性基来 ...
- CF938G Shortest Path Queries(线性基/线段树分治/异或)
CF938G Shortest Path Queries 支持加边删边和查询两点之间的异或最短路,我们可以使用线段树分治,然后利用线性基求解. 但是这里图可能不是联通的,所以查询两点之间的异或和需要边 ...
最新文章
- 涨知识了!网络原来是这样连接的
- python中文昵称-python3随机生成中文字符(随机生成两字或三字的名字)
- memcache 安装与简单使用
- Python按行输出文件内容具体解释及延伸
- poker java idea_JavaBasic学习笔记
- java str2date,java date类与string类实例代码分享
- 消费金融资金断流,银行抽贷、通道暂停,P2P离场
- 整理下STL algorithms(3)
- Spring Boot入门——多文件上传大小超限问题解决
- Drools 7.x Rate算法
- php类方法属性省略,第十课—类的属性和类的方法 2018年9月3日 20时00分
- MySQL JDBC URL中几个重要参数说明
- 字符串的模板 Manacher kmp ac自动机 后缀数组 后缀自动机
- 前阿里P10员工赵海平加入字节跳动,职级或为4+
- 使用微信公众号openid获取用户信息判断是否关注公众号
- 机器人操作臂运动学入门一--D-H参数标定
- 文件以及文件夹的管理
- js逆向--有道翻译
- 记录一下:老衲的py路程 mac下的tkinter小应用
- Pandas库——DataFrame入门
热门文章
- vue实现图片预加载的几种方式
- 微信支付接入-弹出支付框输入密码后一直在转圈,20s后提示:支付失败,请稍后再试
- TCPIP卷一(11):EIGRP的汇总、stub、leak-map参数
- dfuse Labs——展示 dfuse 的力量
- xgboost缺失值处理
- 华为鸿蒙系统平板电脑,华为5G鸿蒙系统平板电脑正式入网,搭载八核处理器麒麟9000芯片...
- matlab的syms无法在函数中使用_matlab syms什么意思_常见问题解析
- R数据分析:如何在R中使用mutate
- uniapp 苹果安全区配置
- STM8学习笔记1:CPU简介