BZOJ 4568: [Scoi2016]幸运数字 [线性基 倍增]
4568: [Scoi2016]幸运数字
题意:一颗带点权的树,求树上两点间异或值最大子集的异或值
显然要用线性基
可以用倍增的思想,维护每个点向上\(2^j\)个祖先这些点的线性基,求lca的时候合并起来就行了
复杂度\(O(nlogn60*60)\)
注意这是点权,特判x==y的情况,需要插入a[x]
还可以用点分治和树链剖分
我的代码好慢啊...但是很好写啊
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
#define fir first
#define sec second
const int N=2e4+5;
inline ll read() {
char c=getchar(); ll x=0, f=1;
while(c<'0' || c>'9') {if(c=='-')f=-1; c=getchar();}
while(c>='0' && c<='9') {x=x*10+c-'0'; c=getchar();}
return x*f;
}
int n, Q, u, v; ll a[N];
struct edge{int v, ne;}e[N<<1];
int cnt=1, h[N];
inline void ins(int u, int v) {
e[++cnt]=(edge){v, h[u]}; h[u]=cnt;
e[++cnt]=(edge){u, h[v]}; h[v]=cnt;
}
namespace lb{
struct meow {
ll p[62];
meow(){memset(p, 0, sizeof(p));}
ll operator [](int x) {return p[x];}
bool insert(ll val) {
for(int i=60; i>=0; i--)
if(val & (1LL<<i)) {
if(p[i]) val ^= p[i];
else {p[i]=val; break;}
}
return val>0;
}
void merge(meow &a) {
for(int i=60; i>=0; i--) if(a[i]) insert(a[i]);
}
ll getmax() {
ll ans=0;
for(int i=60; i>=0; i--) ans = max(ans, ans^p[i]);
return ans;
}
void print() {
for(int i=60; i>=0; i--) if(p[i]) printf("p %d %lld\n",i,p[i]);
puts("");
}
}b[N][17];
}using lb::b; using lb::meow;
int fa[N][17], deep[N];
void dfs(int u) {
for(int i=1; (1<<i)<=deep[u]; i++) {
fa[u][i] = fa[ fa[u][i-1] ][i-1];
b[u][i].merge(b[u][i-1]); b[u][i].merge(b[ fa[u][i-1] ][i-1]);
}
for(int i=h[u];i;i=e[i].ne)
if(e[i].v != fa[u][0]) {
fa[e[i].v][0]=u;
deep[e[i].v]=deep[u]+1;
b[e[i].v][0].insert(a[u]);
dfs(e[i].v);
}
}
meow lca(int x, int y) { //printf("lca %d %d\n",x,y);
meow now;
if(x==y) {now.insert(a[x]); return now;}
if(deep[x]<deep[y]) swap(x, y);
int bin=deep[x]-deep[y];
for(int i=0; i<15; i++)
if((1<<i)&bin) now.merge(b[x][i]), x=fa[x][i];
if(x==y) return now;
for(int i=14; i>=0; i--)
if(fa[x][i] != fa[y][i]) now.merge(b[x][i]), now.merge(b[y][i]), x=fa[x][i], y=fa[y][i];
now.merge(b[x][0]); now.insert(a[y]);
//puts("now");now.print();
return now;
}
ll Que(int x, int y) {
return lca(x, y).getmax();
}
int main() {
freopen("in","r",stdin);
n=read(); Q=read();
for(int i=1; i<=n; i++) a[i]=read(), b[i][0].insert(a[i]);
for(int i=1; i<n; i++) ins(read(), read());
dfs(1);
//for(int i=1; i<=n; i++)
// for(int j=0; (1<<j)<=deep[i]; j++) printf("hi %d %d %d\n",i,j,fa[i][j]), b[i][j].print();
for(int i=1; i<=Q; i++) printf("%lld\n", Que(read(), read()));
}
BZOJ 4568: [Scoi2016]幸运数字 [线性基 倍增]的更多相关文章
- BZOJ 4568 [Scoi2016]幸运数字 ——线性基 倍增
[题目分析] 考虑异或的最大值,维护线性基就可以了. 但是有多次的询问,树剖或者倍增都可以. 想了想树剖动辄数百行的代码. 算了,我还是写倍增吧. 注:被位运算和大于号的优先级坑了一次,QaQ [代码 ...
- 洛谷P3292 [SCOI2016]幸运数字 线性基+倍增
P3292 [SCOI2016]幸运数字 传送门 题目描述 A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个幸运数字,以纪念碑的形式矗立在 ...
- P3292 [SCOI2016]幸运数字 [线性基+倍增]
线性基+倍增 // by Isaunoya #include <bits/stdc++.h> using namespace std; #define rep(i, x, y) for ( ...
- BZOJ4568: [Scoi2016]幸运数字(线性基 倍增)
题意 题目链接 Sol 线性基是可以合并的 倍增维护一下 然后就做完了?? 喵喵喵? // luogu-judger-enable-o2 #include<bits/stdc++.h> # ...
- BZOJ.4516.[SCOI2016]幸运数字(线性基 点分治)
题目链接 线性基可以\(O(log^2)\)暴力合并.又是树上路径问题,考虑点分治. 对于每个点i求解 LCA(u,v)==i 时的询问(u,v),只需求出这个点到其它点的线性基后,暴力合并. LCA ...
- bzoj 4568: [Scoi2016]幸运数字
4568: [Scoi2016]幸运数字 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 848 Solved: 336[Submit][Status ...
- P3292 [SCOI2016]幸运数字 线性基
正解:线性基+倍增 解题报告: 先放下传送门QAQ 然后这题,其实没什么太大的技术含量,,,?就几个知识点套在一起,除了代码长以外没任何意义,主要因为想复习下线性基的题目所以还是写下,,, 随便写下思 ...
- BZOJ 4568: [Scoi2016]幸运数字(倍增+线性基)
传送门 解题思路 异或最大值肯定线性基了,树上两点那么就倍增搞一搞,就维护每个点到各级祖先的线性基,时间复杂度\(O(nlog^3n)\),并不知道咋过去的. 代码 #include<iostr ...
- BZOJ 4568 [Scoi2016]幸运数字(树链剖分 + 异或线性基)
题目链接 BZOJ 4568 考虑树链剖分+线段树维护每一段区域的异或线性基 对于每个询问,求出该点集的异或线性基.然后求一下这个线性基里面能异或出的最大值即可. #include <bits ...
随机推荐
- Spring框架学习笔记(9)——Spring对JDBC的支持
一.使用JdbcTemplate和JdbcDaoSupport 1.配置并连接数据库 ①创建项目并添加jar包,要比之前Spring项目多添加两个jar包c3p0-0.9.1.2.jar和mysql- ...
- 无序列表li横向排列的间隙问题
今天在写页面的时候,无意中遇到这样一个问题,就是无序列表li横向排列即做成导航栏时,列表项间有间隙. 如: 将列表项li变成列表块后(即将li标签设置为,display:inline-block后), ...
- HDU 1233 还是畅通工程(模板——克鲁斯卡尔算法)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1233 题意描述: 输入n个城镇以及n*(n-1)/2条道路信息 计算并输出将所有城镇连通或者间接连通 ...
- Windows7下设置定时启动(关闭)虚拟机
曾记否,忆当年,开启或者关闭虚拟机,度秒如年~ ⒈石头,剪刀,布,C.D.E盘随便找一个,然后在里面找个静谧的墙角, 新建一个文件:vmstart.bat 添加:"C:\Program Fi ...
- 最简Java程序
本文是笔者创建项目--一系列java示例程序的总结.项目位置在SimplestJavaDemos,欢迎访问. 以下为正文: --- 作为一个伪完美主义+拖延癌患者,每次要学习新技术的时候,总是要把 ...
- 数据库连接池(c3p0)
(一)问题的提出: 在使用开发基于数据库的web程序时,传统的数据库使用模式按照以下步骤: 在程序中建立数据库连接 进行sql操作 断开数据库连接 但是,这种模式存在着移动的问题: 传统连接模式每次向 ...
- 关于富文本在Android中的应用以及遇到的坑
富文本可以为用户提供更加多样化的文本展示形式,但由于其使用了H5标签的特殊性,一般都需要第三方框架的支持.这里推荐一款合适的第三方富文本框架,richeditor. 首先我们要使用该功能需要引入相关j ...
- 初次真正意义上的接触Eclipse
以前就玩安卓app 用过很多软件比如e4a,iapp,aide,lua,但是这都不是真正意义上的安卓编程软件.大二的时候用过Androidstudio,那个软件配置起来太难了,就搁置了. 这次利用机智 ...
- Azure Powershell对ASM资源的基本操作
本文主要介绍Windows Azure Powershell对ASM资源的基本操作 1.登陆ASM模式,命令:Add-AzureAccount -Environment AzureChinaCloud ...
- AI_深度学习概论
什么是是神经网络? 假如有6间房屋的数据集,已知房子的面积,单位是平方米或平方英尺,已知房子的价格.如果通过这6间房子的价格和房子的面积,预测房子的价格,首先要建立起一个数据模型 ,x轴为价格,y轴为 ...