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 ...
随机推荐
- HDU1016(素数环)
Prime Ring Problem Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- 用gcc编译c语言程序以及其编译过程
对于初学c语言编程的我们来说,学会如何使用gcc编译器工具,对理解c语言的执行过程,加深对c语言的理解很重要!!! 1.预编译 --> 2.编译 --> 3.汇编 --> 4.链接- ...
- Spring框架学习笔记(2)——IOC&DI
IOC:控制反转,创建对象的权利交给Spring,Spring会自动创建对象. DI:依赖注入,操作的对象靠Spring注入,如果不使用Spring,对象的属性值是要靠setter方法来添加的,使用S ...
- Vue2反向代理
前一段时间写了一个vue2的小项目,用的是vue-cli脚手架搭建的项目,项目里需要跨域,但又不能使用jsonp,上网查了一下,发现有一个之前没接触过的词语--反向代理. 什么是"反向代 ...
- Arrays类详解
数组是数据结构中最简单的一种类型.在平常的使用上也比较多见.今天就来总结一下数组在使用过程中的一些心得 1.java中包装数组的一些基本用法的抽象类 java.util.Arrays.这个类中包含操 ...
- python原始字符串
str1='let's go' File "<input>", line 1 str1='let's go' ^ SyntaxError: invalid syntax ...
- 如何在外部终止一个pengding的promise对象
今天在整理前段时间做过的项目,发现之前在集成web环信的时候遇到过一个奇怪的需求:需要终止一个正在进行等待返回的promise,或者阻止其调用resolve和reject.(具体为何会有这种需求我也不 ...
- 分享如何使用PHP将URL地址参数进行加密传输提高网站安全性
大家在使用PHP进行GET或POST提交数据时,经常会在URL带着参数进行传递,比如www.mdaima.com/get.php?id=1&page=5,这里就将id编号和page页码进行了参 ...
- ngRx 官方示例分析 - 1. 介绍
ngRx 的官方示例演示了在具体的场景中,如何使用 ngRx 管理应用的状态. 示例介绍 示例允许用户通过查询 google 的 book API 来查询图书,并保存自己的精选书籍列表. 菜单有两 ...
- JavaScript常见封装方法
1.最简单的,使用变量,然后用匿名函数包裹,不封装 2.对象字面量简单封装(不完整的模块模式,因为无法达到变量.方法私有效果.不过确实有分离和组织代码的能力,也就算一种简略的模块模式的实现方式) va ...