luogu3292 幸运数字 (点分治+线性基)
首先第一眼是一个倍增套线性基,但是$O(Qlog^2Vlog^N)=10^{10}$的复杂度...
即使是st表也只是变成了$O(Nlog^2Vlog^N)$啊
考虑点分治,相对于倍增显著减少了线性基合并(一个往另一个里暴力插)这一O(log^2V)的过程
就是在分治到一个询问的两端点分立于两个子树的时候,合并它们的线性基来统计答案
#include<bits/stdc++.h>
#define CLR(a,x) memset(a,x,sizeof(a))
#define MP make_pair
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pa;
const int maxn=2e4+,maxq=2e5+; inline ll rd(){
ll x=;char c=getchar();int neg=;
while(c<''||c>''){if(c=='-') neg=-;c=getchar();}
while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x*neg;
} struct Node{
int b,i;
};
int N,Q,siz[maxn];
vector<Node> q[maxn];
int eg[maxn*][],egh[maxn],ect;
bool flag[maxn];
ll base[maxn][],tmp[],val[maxn],ans[maxq];
int son[maxn],sct,bel[maxn]; inline void adeg(int a,int b){
eg[++ect][]=b,eg[ect][]=egh[a],egh[a]=ect;
}
inline void getroot(int x,int f,int ssiz,int &rt,int &sm){
siz[x]=;int m=;
for(int i=egh[x];i;i=eg[i][]){
int b=eg[i][];if(b==f||flag[b]) continue;
getroot(b,x,ssiz,rt,sm);
m=max(siz[b],m);siz[x]+=siz[b];
}m=max(ssiz-siz[x],m);
if(m<sm) rt=x,sm=m;
} inline void update(ll *bs,ll v){
for(int i=;i>=;i--){
if(v&(1ll<<i)){
if(!bs[i]){bs[i]=v;break;}
else v^=bs[i];
}
}
} inline ll query(ll *bs,ll v){
for(int i=;i>=;i--){
if((v^bs[i])>v) v^=bs[i];
}return v;
} inline void getbase(int x,int f){
update(base[x],val[x]);
son[++sct]=x;
for(int i=egh[x];i;i=eg[i][]){
int b=eg[i][];if(b==f||flag[b]) continue;
memcpy(base[b],base[x],sizeof(base[x]));
getbase(b,x);
}
} inline void solve(int x,int ssiz){
flag[x]=;bel[x]=x;CLR(base[x],);
for(int i=egh[x];i;i=eg[i][]){
int b=eg[i][];if(flag[b]) continue;
CLR(base[b],);sct=;
getbase(b,);
for(int i=;i<=sct;i++){
int y=son[i];
for(int j=;j<q[y].size();j++){
int b=q[y][j].b;
if(bel[b]!=x) continue;
memcpy(tmp,base[y],sizeof(tmp));
for(int k=;k<=;k++){
if(base[b][k]) update(tmp,base[b][k]);
}
ans[q[y][j].i]=max(query(tmp,),query(tmp,val[x]));
}
}
for(int i=;i<=sct;i++) bel[son[i]]=x;
}
for(int i=egh[x];i;i=eg[i][]){
int b=eg[i][];if(flag[b]) continue;
int rt,sm=1e9;
getroot(b,,siz[b]>siz[x]?ssiz-siz[x]:siz[b],rt,sm);
solve(rt,siz[b]>siz[x]?ssiz-siz[x]:siz[b]);
}
} int main(){
int i,j,k;
N=rd(),Q=rd();
for(i=;i<=N;i++) val[i]=rd();
for(i=;i<N;i++){
int a=rd(),b=rd();
adeg(a,b);adeg(b,a);
}
for(i=;i<=Q;i++){
int a=rd(),b=rd();
if(a==b) ans[i]=val[a];
else{
q[a].push_back((Node){b,i});
q[b].push_back((Node){a,i});
} }
int rt,sm=1e9;
getroot(,,N,rt,sm);
solve(rt,N);
for(i=;i<=Q;i++)
printf("%lld\n",ans[i]);
return ;
}
luogu3292 幸运数字 (点分治+线性基)的更多相关文章
- loj#2013. 「SCOI2016」幸运数字 点分治/线性基
题目链接 loj#2013. 「SCOI2016」幸运数字 题解 和树上路径有管...点分治吧 把询问挂到点上 求出重心后,求出重心到每个点路径上的数的线性基 对于重心为lca的合并寻味,否则标记下传 ...
- 2019.03.25 bzoj4568: [Scoi2016]幸运数字(倍增+线性基)
传送门 题意:给你一棵带点权的树,多次询问路径的最大异或和. 思路: 线性基上树?? 倍增维护一下就完了. 时间复杂度O(nlog3n)O(nlog^3n)O(nlog3n) 代码: #include ...
- 洛谷P3292 [SCOI2016]幸运数字(倍增+线性基)
传送门 不知道线性基是什么东西的可以看看蒟蒻的总结 第一眼:这不会是个倍增LCA暴力合并线性基吧…… 打了一发……A了? 所以这真的是个暴力倍增LCA合并线性基么…… ps:据某大佬说其实可以离线之后 ...
- SCOI2016幸运数字(树剖/倍增/点分治+线性基)
题目链接 loj luogu 题意 求树上路径最大点权异或和 自然想到(维护树上路径)+ (维护最大异或和) 那么有三种方法可以选择 1.树剖+线性基 2.倍增+线性基 3.点分治+线性基 至于线性基 ...
- BZOJ.4184.shallot(线段树分治 线性基)
BZOJ 裸的线段树分治+线性基,就是跑的巨慢_(:з」∠)_ . 不知道他们都写的什么=-= //41652kb 11920ms #include <map> #include < ...
- $CF938G\ Shortest\ Path\ Queries$ 线段树分治+线性基
正解:线段树分治+线性基 解题报告: 传送门$QwQ$ 考虑如果只有操作3,就这题嘛$QwQ$ 欧克然后现在考虑加上了操作一操作二 于是就线段树分治鸭 首先线段树叶子节点是询问嘛这个不用说$QwQ$. ...
- [BZOJ4568][SCOI2016]幸运数字(倍增LCA,点分治+线性基)
4568: [Scoi2016]幸运数字 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 2131 Solved: 865[Submit][Statu ...
- BZOJ4568 [Scoi2016]幸运数字 【点分治 + 线性基】
题目链接 BZOJ4568 题解 选任意个数异或和最大,使用线性基 线性基插入\(O(logn)\),合并\(O(log^2n)\) 我们要求树上两点间异或和最大值,由于合并是\(O(log^2n)\ ...
- 【BZOJ-4184 】 Shallot 线段树按时间分治 + 线性基
4184: shallot Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 356 Solved: 180[Submit][Status][Discu ...
随机推荐
- 【学亮IT手记】利用字节流复制图片
- Angular 双向数据绑定
<!DOCTYPE html><html ng-app="myApp"><head lang="en"> <meta ...
- 2017年前小纪(有关http的一些缓存理论知识)
position的top和bottom的区别:前者基准点定在top,后者基准点定在bottom. for-in 遍历属性的顺序不确定 手机端,line-height对光标大小非常有影响 有些css3属 ...
- 非关系型数据库----MongoDB
一.什么是MongoDB? MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统. 在高负载的情况下,添加更多的节点,可以保证服务器性能. MongoDB 旨在为WEB应用提 ...
- java学习之—数组的曾删改查
/** * 数组的曾删改查 * Create by Administrator * 2018/6/8 0008 * 上午 9:54 **/ public class HighArray { priva ...
- mycat - 水平分表
相对于垂直拆分的区别是:垂直拆分是把不同的表拆到不同的数据库中,而水平拆分是把同一个表拆到不同的数据库中.水平拆分不是将表的数据做分类,而是按照某个字段的某种规则来分散到多个库之中,每个表中包含一部分 ...
- python之路-列表、元组、range
一 . 列表 # 列表的定义 列表就是能装对象的对象 在python中用[ ]来描述列表,内部元素用逗号隔开,对数据类型没有要求 索引和切片 lst = ["天龙八部", &quo ...
- 用python写一个预警机器人(支持微信和钉钉)
背景 线上的系统在运行中,发生故障时怎么及时的通过手机通知到相关人员?当然这是个很简单的需求,现有的方法有很多,例如: 如果我们用的云产品,那么一般都会有配套对应的监控预警功能,根据需要配置一下即可, ...
- jQ append 添加html 及字符串拼接
如图,我要拼接这样一段html: 点击下边添加按钮,不断添加这段Html html: <div class="x_addtable"> <div class=&q ...
- linux 挂载windows下目录,其它linux机器nfs的目录,自己dd的文件
如有转载,不胜荣幸.http://www.cnblogs.com/aaron-agu/ 挂载window下共享的目录 //192.168.0.11/share /mnt 挂载其它linux机器下目录 ...