【BZOJ-4568】幸运数字 树链剖分 + 线性基合并
4568: [Scoi2016]幸运数字
Time Limit: 60 Sec Memory Limit: 256 MB
Submit: 238 Solved: 113
[Submit][Status][Discuss]
Description
Input
Output
输出需要包含 q 行,每行包含 1 个非负整数,表示这名旅行者可以保留的最大幸运值。
Sample Input
11 5 7 9
1 2
1 3
1 4
2 3
1 4
Sample Output
11
HINT
Source
Solution
树上线性基
感觉可以有多重做法(1)树链剖分+线性基合并(2)LCA+倍增+线性基合并(3)点分治+线性基合并
后两个是$logn$级的,第一种是$log^{2}n$级的,自己一开始算错了复杂度,于是开心的写了(1),不过BZOJ开到60s时限,所以还是可以水过的
大体上就是树链剖分一下,线段树维护区间线性基,两个叶节点的线性基合并起来就是根的线性基,具体的合并,就是直接暴力把一个插入到另一个里面
然后查询的时候正常的查询就好了.
LCA+倍增的做法就是倍增预处理出$2^{j}$步的线性基,预处理和查询的时候,同样都是暴力合并线性基
Code
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstring>
using namespace std;
long long read()
{
long long x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
#define maxn 20010
int n,q; long long val[maxn];
struct EdgeNode{int next,to;}edge[maxn<<];
int head[maxn],cnt;
void add(int u,int v) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;}
void insert(int u,int v) {add(u,v); add(v,u);}
//==============================================================================================
int size[maxn],deep[maxn],fa[maxn],son[maxn],pl[maxn],sz,pr[maxn],top[maxn];long long pre[maxn];
void dfs_1(int now)
{
size[now]=;
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].to!=fa[now])
{
deep[edge[i].to]=deep[now]+;
fa[edge[i].to]=now;
dfs_1(edge[i].to);
if (size[edge[i].to]>size[son[now]]) son[now]=edge[i].to;
size[now]+=size[edge[i].to];
}
}
void dfs_2(int now,int chain)
{
pl[now]=++sz; pre[sz]=val[now]; top[now]=chain;
if (son[now]) dfs_2(son[now],chain);
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].to!=fa[now] && edge[i].to!=son[now])
dfs_2(edge[i].to,edge[i].to);
pr[now]=sz;
}
//==============================================================================================
struct XXJ{long long a[];}Ans;
struct TreeNode{int l,r;XXJ X;}tree[maxn<<];
void Merge(XXJ &x,XXJ &y,XXJ &z)
{
XXJ tmp;
for (int i=; i>=; i--) tmp.a[i]=y.a[i];
for (int i=; i>=; i--)
if (z.a[i])
{
long long tp=z.a[i];
for (int i=; i>=; i--)
if (tp&(1LL<<i))
if (!tmp.a[i]) {tmp.a[i]=tp; break;}
else tp^=tmp.a[i];
}
for (int i=; i>=; i--) x.a[i]=tmp.a[i];
}
void BuildTree(int now,int l,int r)
{
tree[now].l=l; tree[now].r=r;
if (l==r)
{
memset(tree[now].X.a,0LL,sizeof(tree[now].X.a));
long long tp=pre[l];
for (int i=; i>=; i--)
if (tp&(1LL<<i))
if (!tree[now].X.a[i]) {tree[now].X.a[i]=tp; break;}
else tp^=tree[now].X.a[i];
return;
}
int mid=(l+r)>>;
BuildTree(now<<,l,mid); BuildTree(now<<|,mid+,r);
Merge(tree[now].X,tree[now<<].X,tree[now<<|].X);
}
void Query(int now,int L,int R)
{
if (L<=tree[now].l && R>=tree[now].r) {Merge(Ans,Ans,tree[now].X); return;}
int mid=(tree[now].l+tree[now].r)>>;
if (L<=mid) Query(now<<,L,R);
if (R>mid) Query(now<<|,L,R);
}
//==============================================================================================
void Solve_Query(int x,int y)
{
while (top[x]!=top[y])
{
if (deep[top[x]]<deep[top[y]]) swap(x,y);
Query(,pl[top[x]],pl[x]);
x=fa[top[x]];
}
if (deep[x]>deep[y]) swap(x,y);
Query(,pl[x],pl[y]);
}
//==============================================================================================
int main()
{
n=read();q=read();
for (int i=; i<=n; i++) val[i]=read();
for (int u,v,i=; i<=n-; i++) u=read(),v=read(),insert(u,v);
dfs_1(); dfs_2(,); BuildTree(,,n);
while (q--)
{
int x=read(),y=read(); long long ans=;
memset(Ans.a,0LL,sizeof(Ans.a));
Solve_Query(x,y);
for (int i=; i>=; i--) if ((ans^Ans.a[i])>ans) ans^=Ans.a[i];
printf("%lld\n",ans);
}
return ;
}
谢谢YJQ大大的数据,考前A题的快感
【BZOJ-4568】幸运数字 树链剖分 + 线性基合并的更多相关文章
- [SCOI2016]幸运数字 树链剖分,线性基
[SCOI2016]幸运数字 LG传送门 为了快乐,我们用树剖写这题. 强行树剖,线段树上每个结点维护一个线性基,每次查询暴力合并. 瞎分析一波复杂度:树剖两点之间\(\log n\)条重链,每条重链 ...
- 「洛谷3292」「BZOJ4568」「SCOI2016」幸运数字【倍增LCA+线性基+合并】
[bzoj数据下载地址]不要谢我 先讲一下窝是怎么错的... \(MLE\)是因为数组开小了.. 看到异或和最大,那么就会想到用线性基. 如果不会线性基的可以参考一下我的学习笔记:「线性基」学习笔记a ...
- 【CodeChef EDGEST】Edges in Spanning Trees(树链剖分+树上启发式合并)
点此看题面 大致题意: 给你两棵\(n\)个点的树,对于第一棵树中的每条边\(e_1\),求存在多少条第二棵树中的边\(e_2\),使得第一棵树删掉\(e_1\)加上\(e_2\).第二棵树删掉\(e ...
- BZOJ 3531 [Sdoi2014]旅行 树链剖分+动态开点线段树
题意 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰. 为了方便,我们用 ...
- BZOJ 3531: [Sdoi2014]旅行 [树链剖分]
3531: [Sdoi2014]旅行 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1685 Solved: 751[Submit][Status] ...
- BZOJ 2243: [SDOI2011]染色 [树链剖分]
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 6651 Solved: 2432[Submit][Status ...
- [BZOJ - 2819] Nim 【树链剖分 / DFS序】
题目链接: BZOJ - 2819 题目分析 我们知道,单纯的 Nim 的必胜状态是,各堆石子的数量异或和不为 0 .那么这道题其实就是要求求出树上的两点之间的路径的异或和.要求支持单点修改. 方法一 ...
- BZOJ.4515.[SDOI2016]游戏(树链剖分 李超线段树)
BZOJ 洛谷 每次在路径上加的数是个一次函数,容易看出是树剖+李超线段树维护函数最小值.所以其实依旧是模板题. 横坐标自然是取个确定的距离标准.取每个点到根节点的距离\(dis[i]\)作为\(i\ ...
- bzoj 4448 [Scoi2015]情报传递 (树链剖分+主席树)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4448 题面: Description 奈特公司是一个巨大的情报公司,它有着庞大的情报网络 ...
随机推荐
- 清北学堂2017NOIP冬令营入学测试P4749 C’s problem(c)
P4746 C's problem(c) 时间: 1000ms / 空间: 655360KiB / Java类名: Main 背景 冬令营入学测试 描述 题目描述 小C是一名数学家,由于它自制力比较差 ...
- perl 下使用非root用户安装模块
perl下安装模块可以使用cpan命令,但是通常我们不具有root用户权限,所以只能以sudo方式安装模块. 例如需要安装Net::SCP::Expect模块, 执行cpan Net::SCP::Ex ...
- TopCoder
在TopCoder下载好luncher,网址:https://www.topcoder.com/community/competitive%20programming/ 选择launch web ar ...
- 求解区间最值 - RMQ - ST 算法介绍
解析 ST 算法是 RMQ(Range Minimum/Maximum Query)中一个很经典的算法,它天生用来求得一个区间的最值,但却不能维护最值,也就是说,过程中不能改变区间中的某个元素的值.O ...
- Linux vmstat命令实战详解
vmstat命令是最常见的Linux/Unix监控工具,可以展现给定时间间隔的服务器的状态值,包括服务器的CPU使用率,内存使用,虚拟内存交换情况,IO读写情况.这个命令是我查看Linux/Unix最 ...
- [BZOJ3714][PA2014]Kuglarz(MST)
题目: Description 魔术师的桌子上有n个杯子排成一行,编号为1,2,…,n,其中某些杯子底下藏有一个小球,如果你准确地猜出是哪些杯子,你就可以获得奖品.花费c_ij元,魔术师就会告诉你杯子 ...
- C程序两则
<span style="font-size:24px;">#include<iostream> using namespace std; int *fun ...
- RabbitMQ官方中文入门教程(PHP版) 第一部分:Hello World
RabbitMQ是一个消息代理.它的核心原理非常简单:接收和发送消息.你可以把它想像成一个邮局:你把信件放入邮箱,邮递员就会把信件投递到你的收件人处.在这个比喻中,RabbitMQ是一个邮箱.邮局.邮 ...
- jq不包含某属性
jq解释属性选择器时有以下四种: 上面都是带某属性或者属性为某值的情况,还有一种情况是不带某属性怎么办? 答案是同属性不为某值. 如 <a b='c' class="d"&g ...
- Visual Studio 2013启用AnkSVN
1. 官网下载AnkSVN https://ankhsvn.open.collab.net/ 2. 安装 3. 启用 When you enable AnkhSVN as a VS.NET sour ...