bzoj4568-幸运数字
题目
给出一棵树,每个节点上有权值\(a_i\),多次询问一条路径上选择一些点权值异或和最大值。\(n\le 2\times 10^4,q\le 2\times 10^5,0\le a_i\le 2\times 2^{60}\)。
分析
选择一些点的异或和最大值显然用到线性基,这又是一个树上的路径问题,所以可以考虑倍增。预处理出倍增线性基,查询的时候倍增合并线性基,利用线性基的方法查询(从高往低能变大就异或)最大值。
这个总复杂度为\(O((n+q)\log n\log^2 a)\)。(线性基插入为\(\log a\),合并的时候有\(\log a\)个要插入)。
算起来是非常大的呢!但是可以过!
于是就开始寻找更好的做法。
有两种更好的方法,参考上面zwl的博客。
首先由于线性基重复是不影响的,所以可以直接按 \(O(1)\) RMQ的方法来做,这样一共最多只需要合并4次线性基,所以就少掉一个log!
另一种做法是用点分治离线处理询问。对于每个重心求出到每个子树中节点的线性基,再给子树标号,判断当前重心上的询问是否通过重心。如果是的话就合并一次线性基得到答案,否则就把询问丢进所在的子树中。
这样总复杂度为\(O(n\log n\log a+q\log ^2a+q\log n)\),分别是点分构建线性基,总询问复杂度和每层扫描询问复杂度。
很奇妙呢!!
代码
于是我写的是开始的正常(不科学)方法。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long giant;
const int maxn=2e4+1;
const int maxj=15;
const int maxg=61;
int n,m,f[maxn][maxj],dep[maxn];
giant a[maxn];
struct base {
giant a[maxg];
inline void clear() {memset(a,0,sizeof a);}
base () {clear();}
void insert(giant x) {
for (int j=maxg-1;j>=0;--j) if ((x>>j)&1) {
if ((a[j]>>j)&1) x^=a[j]; else {
a[j]=x;
break;
}
}
}
giant mx() {
giant ret=0;
for (int j=maxg-1;j>=0;--j) if ((ret^a[j])>ret) ret^=a[j];
return ret;
}
} b[maxn][maxj];
base operator + (base a,base b) {
for (int j=maxg-1;j>=0;--j) if (b.a[j]) a.insert(b.a[j]);
return a;
}
vector<int> g[maxn];
inline void add(int x,int y) {g[x].push_back(y);}
void dfs(int x,int fa) {
f[x][0]=fa;
dep[x]=dep[fa]+1;
for (int v:g[x]) if (v!=fa) {
b[v][0].insert(a[x]);
dfs(v,x);
}
}
int lca(int x,int y) {
if (dep[x]<dep[y]) swap(x,y);
for (int j=maxj-1;j>=0;--j) if (dep[f[x][j]]>=dep[y]) x=f[x][j];
if (x==y) return x;
for (int j=maxj-1;j>=0;--j) if (f[x][j]!=f[y][j]) x=f[x][j],y=f[y][j];
return f[x][0];
}
base get(int x,int p) {
base ret;
ret.insert(a[x]);
for (int j=maxj-1;j>=0;--j) if (dep[f[x][j]]>=dep[p]) ret=ret+b[x][j],x=f[x][j];
return ret;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
#endif
scanf("%d%d",&n,&m);
for (int i=1;i<=n;++i) scanf("%lld",a+i);
for (int i=1;i<n;++i) {
int x,y;
scanf("%d%d",&x,&y);
add(x,y),add(y,x);
}
dfs(1,1);
for (int j=1;j<maxj;++j) for (int i=1;i<=n;++i) {
f[i][j]=f[f[i][j-1]][j-1];
b[i][j]=b[i][j-1]+b[f[i][j-1]][j-1];
}
while (m--) {
int x,y;
scanf("%d%d",&x,&y);
if (x==y) {
printf("%lld\n",a[x]);
continue;
}
if (dep[x]>dep[y]) swap(x,y);
int l=lca(x,y);
base c=(x==l?get(y,l):get(x,l)+get(y,l));
giant ans=c.mx();
printf("%lld\n",ans);
}
return 0;
}
bzoj4568-幸运数字的更多相关文章
- 【bzoj4568 scoi2016】幸运数字
题目描述 A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个幸运数字,以纪念碑的形式矗立在这座城市的正中心,作为城市的象征. 一些旅行者希望 ...
- 【BZOJ4568】幸运数字(线性基,树链剖分,ST表)
[BZOJ4568]幸运数字(线性基,树链剖分,ST表) 题面 BZOJ Description A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市 ...
- [BZOJ4568][SCOI2016]幸运数字(倍增LCA,点分治+线性基)
4568: [Scoi2016]幸运数字 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 2131 Solved: 865[Submit][Statu ...
- 【BZOJ4568】[Scoi2016]幸运数字 倍增+线性基
[BZOJ4568][Scoi2016]幸运数字 Description A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个幸运数字,以纪念 ...
- 【BZOJ-4568】幸运数字 树链剖分 + 线性基合并
4568: [Scoi2016]幸运数字 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 238 Solved: 113[Submit][Status ...
- BZOJ4568:[SCOI2016]幸运数字——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4568 https://www.luogu.org/problemnew/show/P3292 A ...
- [BZOJ4568][Scoi2016]幸运数字 倍增+线性基
4568: [Scoi2016]幸运数字 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 1791 Solved: 685[Submit][Statu ...
- 【线性基合并 树链剖分】bzoj4568: [Scoi2016]幸运数字
板子题 Description A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个 幸运数字,以纪念碑的形式矗立在这座城市的正中心,作为城市 ...
- 【bzoj4568】[Scoi2016]幸运数字 树上倍增+高斯消元动态维护线性基
题目描述 A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个幸运数字,以纪念碑的形式矗立在这座城市的正中心,作为城市的象征.一些旅行者希望游 ...
- 【bzoj4568】【Scoi2016】幸运数字 (线性基+树上倍增)
Description A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个幸运数字,以纪念碑的形式矗立在这座城市的正中心,作为城市的象征.一 ...
随机推荐
- 20155313 2016-2017-2《Java程序设计》课程总结
20155313 2016-2017-2<Java程序设计>课程总结 目录 一.每周作业链接汇总 二.实验报告链接汇总 三.代码托管链接 四.课堂项目实践 五.课程收获与不足 六.问卷调查 ...
- POI导出excel文件样式
需求: 公司业务和银行挂钩,各种形式的数据之间交互性比较强,这就涉及到了存储形式之间的转换 比如数据库数据与excel文件之间的转换 解决: 我目前使用过的是POI转换数据库和文件之间的数据,下边上代 ...
- High Water Mark 图示
+---- high water mark of newly created table | V +-------------------------------------------------- ...
- python爬虫-爬取盗墓笔记
本来今天要继续更新 scrapy爬取美女图片 系列文章,可是发现使用免费的代理ip都非常不稳定,有时候连接上,有时候连接不上,所以我想找到稳定的代理ip,下次再更新 scrapy爬取美女图片之应对反 ...
- 同一个电脑配置两个Git问题
拿到公司电脑后,正常配置gitlab,以及设置邮箱等等,可以使用公司邮箱,以及一系列设置 git config --global user.name "userName" git ...
- 【转】微信小程序实现自动化测试
山雨欲来风满楼,最近微信小程序相关开发文章吹遍大江南北,亦有摧枯拉朽万象更新之势.问小程序形为何物,直教IT众生怡情悦性高潮迭起.作为一名有着远大理想“包袱”与互联网变革 “使命感”的测试工程师,我再 ...
- flexbox的应用
2009年,display: box 就已经出现,但是直到IE11的发布,全部的主流浏览器才统一支持新的用法display: flex. 这里只说应用,浏览器的兼容处理会附在文章的末尾. 起步 在现代 ...
- 机器学习与R语言——基本语法
一.注释 1.选中要注释的内容,快捷键Ctrl+Shift+C(取消注释方法相同) 2.在需注释内容前输入# #需注释的内容 3.利用if语句,将判断条件设置为false则可跳过if语句中的内容,相当 ...
- Ubuntu常用shell命令
目录 ls cd mkdir mv cp scp rm df du chmod chown chgrp head tail screen apt-get Ubuntu常用shell命令 Ubuntu作 ...
- Android错误:can not get file data of lua/start_v2.op [LUA ERROR] [string "require "lua/start_v2””] 已解决
错误: can not get file data of lua/start_v2.op [LUA ERROR] [string "require "lua/start_v2””] ...