BZOJ4568 [Scoi2016]幸运数字 【点分治 + 线性基】
题目链接
题解
选任意个数异或和最大,使用线性基
线性基插入\(O(logn)\),合并\(O(log^2n)\)
我们要求树上两点间异或和最大值,由于合并是\(O(log^2n)\)的,我们尽量只合并一次
那就采用点分治
每次求出到分治重心的线性基,将过分治重心的询问的两个线性基合并即可
复杂度\(O(60^2q + 60nlogn)\)
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
using namespace std;
const int maxn = 20005,maxm = 200005,INF = 1000000000;
inline LL read(){
LL out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
struct Bit{
LL A[60];
void init(){for (int i = 59; ~i; i--) A[i] = 0;}
void copy(LL* B){for (int i = 59; ~i; i--) A[i] = B[i];}
void ins(LL x){
for (int i = 59; ~i; i--)
if ((x >> i) & 1){
if (A[i]) x ^= A[i];
else {A[i] = x; break;}
}
}
LL ask(){
LL re = 0;
for (int i = 59; ~i; i--) if ((re ^ A[i]) > re) re ^= A[i];
return re;
}
}B[maxn],T;
int h[maxn],ne = 1;
struct EDGE{int to,nxt;}ed[maxn << 1];
inline void build(int u,int v){
ed[++ne] = (EDGE){v,h[u]}; h[u] = ne;
ed[++ne] = (EDGE){u,h[v]}; h[v] = ne;
}
int g[maxn],nxt[30 * maxm],tq[30 * maxn],cnt;
int n,q,x[maxm],y[maxm],vis[maxn],pos[maxn],Vis[maxn],now;
LL G[maxn],ans[maxm];
void Add(int u,int v){
nxt[++cnt] = g[u]; tq[cnt] = v; g[u] = cnt;
}
int F[maxn],siz[maxn],fa[maxn],N,rt;
void getrt(int u){
F[u] = 0; siz[u] = 1;
Redge(u) if (!vis[to = ed[k].to] && to != fa[u]){
fa[to] = u; getrt(to);
siz[u] += siz[to];
F[u] = max(F[u],siz[to]);
}
F[u] = max(F[u],N - siz[u]);
if (F[u] < F[rt]) rt = u;
}
void dfs(int u,int R){
pos[u] = R; siz[u] = 1; Vis[u] = now;
B[u].copy(B[fa[u]].A); B[u].ins(G[u]);
Redge(u) if (!vis[to = ed[k].to] && to != fa[u]){
fa[to] = u; dfs(to,R);
siz[u] += siz[to];
}
}
void solve(int u){
F[rt = 0] = INF; N = siz[u]; getrt(u);
//printf("u%d rt%d\n",u,rt);
pos[rt] = rt; vis[rt] = true; siz[u] = 1; Vis[rt] = ++now;
B[rt].init(); B[rt].ins(G[rt]);
Redge(rt) if (!vis[to = ed[k].to]){
fa[to] = rt; dfs(to,to);
siz[u] += siz[to];
}
for (int k = g[u],i,a,b; k; k = nxt[k]){
i = tq[k]; a = x[i]; b = y[i];
if (Vis[a] != now || Vis[b] != now) continue;
if (pos[a] == pos[b]) Add(pos[a],i);
else {
T.copy(B[a].A);
for (int j = 59; ~j; j--)
if (B[b].A[j]) T.ins(B[b].A[j]);
ans[i] = T.ask();
}
}
Redge(rt) if (!vis[to = ed[k].to]){
solve(to);
}
}
int main(){
n = read(); q = read();
for (int i = 1; i <= n; i++) G[i] = read();
for (int i = 1; i < n; i++) build(read(),read());
for (int i = 1; i <= q; i++){
x[i] = read(); y[i] = read();
if (x[i] == y[i]) ans[i] = G[x[i]];
else Add(1,i);
}
siz[1] = n; solve(1);
for (int i = 1; i <= q; i++)
printf("%lld\n",ans[i]);
return 0;
}
BZOJ4568 [Scoi2016]幸运数字 【点分治 + 线性基】的更多相关文章
- 2019.03.25 bzoj4568: [Scoi2016]幸运数字(倍增+线性基)
传送门 题意:给你一棵带点权的树,多次询问路径的最大异或和. 思路: 线性基上树?? 倍增维护一下就完了. 时间复杂度O(nlog3n)O(nlog^3n)O(nlog3n) 代码: #include ...
- loj#2013. 「SCOI2016」幸运数字 点分治/线性基
题目链接 loj#2013. 「SCOI2016」幸运数字 题解 和树上路径有管...点分治吧 把询问挂到点上 求出重心后,求出重心到每个点路径上的数的线性基 对于重心为lca的合并寻味,否则标记下传 ...
- luogu3292 幸运数字 (点分治+线性基)
首先第一眼是一个倍增套线性基,但是$O(Qlog^2Vlog^N)=10^{10}$的复杂度... 即使是st表也只是变成了$O(Nlog^2Vlog^N)$啊 考虑点分治,相对于倍增显著减少了线性基 ...
- 洛谷P3292 [SCOI2016]幸运数字(倍增+线性基)
传送门 不知道线性基是什么东西的可以看看蒟蒻的总结 第一眼:这不会是个倍增LCA暴力合并线性基吧…… 打了一发……A了? 所以这真的是个暴力倍增LCA合并线性基么…… ps:据某大佬说其实可以离线之后 ...
- [BZOJ4568][SCOI2016]幸运数字(倍增LCA,点分治+线性基)
4568: [Scoi2016]幸运数字 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 2131 Solved: 865[Submit][Statu ...
- [BZOJ4568][Scoi2016]幸运数字 倍增+线性基
4568: [Scoi2016]幸运数字 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 1791 Solved: 685[Submit][Statu ...
- bzoj4568: [Scoi2016]幸运数字(LCA+线性基)
4568: [Scoi2016]幸运数字 题目:传送门 题解: 好题!!! 之前就看过,当时说是要用线性基...就没学 填坑填坑: %%%线性基 && 神犇 主要还是对于线性基的运用和 ...
- 【线性基合并 树链剖分】bzoj4568: [Scoi2016]幸运数字
板子题 Description A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个 幸运数字,以纪念碑的形式矗立在这座城市的正中心,作为城市 ...
- bzoj4568 [Scoi2016]幸运数字 线性基+树链剖分
A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个 幸运数字,以纪念碑的形式矗立在这座城市的正中心,作为城市的象征.一些旅行者希望游览 A ...
随机推荐
- hadoop搭建----centos免密码登录、修改hosts文件
分布式系统在传输数据时需要多台电脑免密码登录 如:A(192.168.227.12)想ssh免密码登录到B(192.168.227.12),需要把A的公钥文件(~/.ssh/id_rsa.pub)里内 ...
- 学习photoshop心得
简要的学习了ps的三大功能p图,抠图,作图, p图主要是学了换脸这一效果,用到套索工具,把范冰冰的脸接到郭德纲身上, 首先使用套索工具把脸圈起来 然后移动到 另一个人脸上 再然后混合图层,自动混合 差 ...
- SEARCH(文字の検索)
文字列に関する無効命令 以下の各命令は無効であり.4.6 および 6.10 までのリリースとの互換性を確保するためにのみ利用可能となっています.これらの命令が古いプログラムの中に出現することはあります ...
- oracle 数据被修改怎么修复?(闪回)
数据被删除 或者 update 的时候忘记勾选where 限制条件,数据全部更新了? 怎么办? 要跑路了? NO !!! 看下面,迅速帮你闪回数据! demo sql: 1. SELECT * FR ...
- Python操作nosql数据库之redis
一.NoSQL的操作 NoSQL,泛指非关系型的数据库.随着互联网web2.0网站的兴起,传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不 ...
- PRO*C 函数事例 2 -- 数据库操作
Pro*C Oracle 的嵌入式开发,数据库处理部分最好能提取到一个模块,按照对不同数据库表的操作分成不同的.pc文件(如 DbsInstStat.pc).将此模块编译成库(c文件编译时链接此库), ...
- itop-4412开发板学习-内核信号量
1. 翻翻书看下,linux提供两种信号量,内核信号量,由内核控制路径使用,System V IPC信号量,由用户态进程使用.下面的就是内核部分的信号量.内核信号量类似于自旋锁,当锁关闭着时,不允许内 ...
- Spring MVC 开发 配置
1.首先在web.xml中配置一个DispatcherServlet,并通过<servlet-mapping>指定需要拦截的url. 下面xml中配置一个拦截.html为后缀的url. & ...
- 前端技术Jquery与Ajax使用总结
前端技术Jquery与Ajax使用总结 虽然主要是做的后端,但是由于有些时候也要写写前台的界面,因此也就学习了下Jquery和Ajax的一些知识,虽说此次写的这些对于前端大神来说有些班门弄斧的感觉,但 ...
- 【js笔记】数组那些事[0]
js中数组是一个特殊的对象,索引是它的属性,整数索引在内部被转化为字符串类型. 1 数组的创建 new关键字方法:var arr=new Array() var arr=new Array(10); ...