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 ...
随机推荐
- 命运(经典dp)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2571 命运 Time Limit: 2000/1000 MS (Java/Others) Mem ...
- SpringMVC框架学习笔记——各种异常、报错解决
1.Target runtime com.genuitec.runtime.generic.jee60 is not defined. 找到导入项目的.setting文件夹org.eclipse.ws ...
- Lua语言的介绍和编程语言的归类
Lua 本条目介绍的是一种编程语言.关于关于Lua在维基百科中的使用,请见"维基百科:Lua".关于"Lua"一词的其他意思,请见"卢阿". ...
- logback的使用和logback.xml详解
一.logback的介绍 Logback是由log4j创始人设计的另一个开源日志组件,官方网站: http://logback.qos.ch.它当前分为下面下个模块: logback-core:其它两 ...
- 分布式文件系统FastDFS动态扩容
当用户量越来越大,则集群中某个group总会到达其极限,这时就得扩展集群的容量了. FastDFS的扩容分为对group纵向扩容和横向扩容 纵向扩容 指在同一个group组中增加服务器,实现数据冗余, ...
- Web前端:如何实现选择select下拉框选中跳转其他页面
<select onchange="window.location=this.value;"><option value="a.html"&g ...
- MySql Host is blocked because of many connection errors;
错误:Host is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts' 原因: 同一个i ...
- 如何更改Linux的ssh端口
1. 修改/etc/ssh/sshd_config里的Port字段 Port 22改为Port 1000(你自定义的端口) 2. 重启sshd服务 #service sshd restart
- ios 一步一步学会自定义地图吹出框(CalloutView)-->(百度地图,高德地图,google地图)
前言 在 ios上边使用地图库的同学肯定遇到过这样的问题:吹出框只能设置title和subtitle和左右的view,不管是百度地图还是高德地图还是自带的 google地图,只提供了这四个属性,如果想 ...
- Linuxc - 执行c程序
1.新建工作空间 root@jiqing-virtual-machine:~/cspace/les1# pwd /root/cspace/les1 2.新建c程序 root@jiqing-virtua ...