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]幸运数字 [线性基 倍增]的更多相关文章

  1. BZOJ 4568 [Scoi2016]幸运数字 ——线性基 倍增

    [题目分析] 考虑异或的最大值,维护线性基就可以了. 但是有多次的询问,树剖或者倍增都可以. 想了想树剖动辄数百行的代码. 算了,我还是写倍增吧. 注:被位运算和大于号的优先级坑了一次,QaQ [代码 ...

  2. 洛谷P3292 [SCOI2016]幸运数字 线性基+倍增

    P3292 [SCOI2016]幸运数字 传送门 题目描述 A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个幸运数字,以纪念碑的形式矗立在 ...

  3. P3292 [SCOI2016]幸运数字 [线性基+倍增]

    线性基+倍增 // by Isaunoya #include <bits/stdc++.h> using namespace std; #define rep(i, x, y) for ( ...

  4. BZOJ4568: [Scoi2016]幸运数字(线性基 倍增)

    题意 题目链接 Sol 线性基是可以合并的 倍增维护一下 然后就做完了?? 喵喵喵? // luogu-judger-enable-o2 #include<bits/stdc++.h> # ...

  5. BZOJ.4516.[SCOI2016]幸运数字(线性基 点分治)

    题目链接 线性基可以\(O(log^2)\)暴力合并.又是树上路径问题,考虑点分治. 对于每个点i求解 LCA(u,v)==i 时的询问(u,v),只需求出这个点到其它点的线性基后,暴力合并. LCA ...

  6. bzoj 4568: [Scoi2016]幸运数字

    4568: [Scoi2016]幸运数字 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 848  Solved: 336[Submit][Status ...

  7. P3292 [SCOI2016]幸运数字 线性基

    正解:线性基+倍增 解题报告: 先放下传送门QAQ 然后这题,其实没什么太大的技术含量,,,?就几个知识点套在一起,除了代码长以外没任何意义,主要因为想复习下线性基的题目所以还是写下,,, 随便写下思 ...

  8. BZOJ 4568: [Scoi2016]幸运数字(倍增+线性基)

    传送门 解题思路 异或最大值肯定线性基了,树上两点那么就倍增搞一搞,就维护每个点到各级祖先的线性基,时间复杂度\(O(nlog^3n)\),并不知道咋过去的. 代码 #include<iostr ...

  9. BZOJ 4568 [Scoi2016]幸运数字(树链剖分 + 异或线性基)

    题目链接  BZOJ 4568 考虑树链剖分+线段树维护每一段区域的异或线性基 对于每个询问,求出该点集的异或线性基.然后求一下这个线性基里面能异或出的最大值即可. #include <bits ...

随机推荐

  1. python程序的标准输入输出

    1,  A+B Problem : http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=1000 #! ...

  2. 常用Windows DOS命令项目部署经常用到

    img { max-width: 100% } 前两天部署.netcore项目,首先是生产环境域名访问不了,再到.netcore项目IIS部署502.5,在到莫名其妙的500,在排查项目部署问题的时候 ...

  3. load和DOMContenLoaded的区别

    load和DOMContentLoaded的作用就是当页面加载完成的时候自动执行,但他们执行的时间点是不一样的. DOM文档加载步骤: (1)解析html结构 (2)加载外部脚本和样式表文件 (3)解 ...

  4. HTTPS和HTTP的区别是什么?

    广泛应用于互联网世界的HTTP想必是大家再熟悉不过的了,然而细心的朋友可能发现淘宝.百度.网上银行等网站都变成HTTPS开头,并且还有一把小绿锁挂在地址栏,那么HTTPS和HTTP的区别是什么呢? 一 ...

  5. HTML 5 <canvas> 标签

    <!DOCTYPE HTML> <html> <body> <canvas id="myCanvas">your browser d ...

  6. python通过scapy模块进行arp断网攻击

    前言: 想实现像arpsoof一样的工具 arp断网攻击原理: 通过伪造IP地址与MAC地址实现ARP欺骗,在网络发送大量ARP通信量.攻击者 只要持续不断发送arp包就能造成中间人攻击或者断网攻击. ...

  7. OKMX6Q ffmpeg & ffserver

    通过ltib在根文件系统中增加mplayer和ffmpeg后,拟使用ffmpeg从摄像头(/dev/video0)采集视频. 刚开始使用了: ffmpeg -f video4linux2 -s 320 ...

  8. Java 反射和内省实现spring的IOC和DI

    1.构造两个JavaBean package com.spring.model; public class People { private Car car; public Car getCar() ...

  9. Linux - ubuntu 设置固定ip和设置dns

    ubuntu 设置固定ip和设置dns 1.ifconfig 查看网卡名称 root@jiqing-virtual-machine:~# ifconfig ens32 Link encap:以太网 硬 ...

  10. 关于ls命令的实例

    生活映射程序---------科技创造生活 ls 是Linux的常用命令之一直接使用 ls 命令的话只会列出对应的文件名ls -l 命令会显示文件和目录,包括文件类型,大小,修改日期和时间,权限信息等 ...