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 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个幸运数字,以纪念碑的形式矗立在这座城市的正中心,作为城市的象征.一 ...
随机推荐
- PHP学习笔记之析构函数以及static,self,parent关键字
引用 $jordan1 = &$jordan; 当jordan1 = null; //此时会直接调用析构函数 而当无&时,就需要等到所有的引用都为null时,才调用析构函数析构 乔丹 ...
- 【HDU3117】Fibonacci Numbers
[HDU3117]Fibonacci Numbers 题面 求斐波那契数列的第\(n\)项的前四位及后四位. 其中\(0\leq n<2^{32}\) 题解 前置知识:线性常系数齐次递推 其实后 ...
- R小问题
步骤 > library(xlsx) > test<-read.csv("I:/山农大学大数据中心/柱状图/z7.csv") > data1=test[] ...
- php实现快速排序和冒泡排序
快速排序 实现思路:把第一个元素作为标记,依次判断后续的值,如果小于它则放在左边,如果大于它则放右边,同理把左右两部分看成一个整体一直递归,最后再数组拼接起来 它的最优时间复杂度为O(nlogn)[以 ...
- 怎样安装Scrapy
Windows怎样安装Scrapy? pip install scrapy会报错 访问https://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted 下载并放到 ...
- 四、Django之模型与管理后台-Part 2
一.数据库安装 打开mysite/settings.py配置文件,这是整个Django项目的设置中心.Django默认使用SQLite数据库,因为Python源生支持SQLite数据库,所以你无须安装 ...
- YAML 基础
YAML 基础 简介 对象 数组 常量 引用 1. 简介 YAML 是专门用来写配置文件的语言,非常简洁和强大! 它的基本语法规则有: 大小写敏感: 使用缩进表示层级关系: 缩进时不允许使用 Tab ...
- Thunder团队——bug修正
团队:欢迎来怼 发现的问题: 1.首先用户通过爱阅APP内部的网址跳转到各大电子书网站时,需要额外启动手机自身浏览器:就以豆瓣网为例,阅读豆瓣网上的一些书籍,是跳转到手机自带浏览器的,APP内部提供的 ...
- 20172305 2018-2019-1 《Java软件结构与数据结构》第八周学习总结
20172305 2018-2019-1 <Java软件结构与数据结构>第八周学习总结 教材学习内容总结 本周内容主要为书第十二章内容: 堆(附加属性的二叉树) 完全二叉树 (最小堆)对于 ...
- 【转】nodeJs学习之项目结构
新建的项目结构应该是这样 bin:项目的启动文件,也可以放其他脚本. node_modules:用来存放项目的依赖库. public:用来存放静态文件(css,js,img). routes:路由控制 ...