【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 奈特公司是一个巨大的情报公司,它有着庞大的情报网络 ...
随机推荐
- BZOJ 1026 【SCOI2009】 windy数
Description windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道, 在A和B之间,包括A和B,总共有多少个windy数? I ...
- AngularJS+Node的RESTful之基本实现
欢迎大家指导与讨论 : ) 一.前言 本文主要讲述RESTful在node端与AngularJS两端配合的基本实现方法,为了尽量做到大家易看易懂,因此文章也没有深入探讨(其实是小鹏我只学到目前这些 - ...
- 内网机(无网络安装 .NET Core win开发环境
1.安装 vs2015 update3 2.按顺序安装以下包 DotNetCore.1.0.0-SDK.Preview2-x64.exe aspnetcoremodule_x64_en_rc2_14. ...
- Web服务器父与子 Apache和Tomcat区别
http://developer.51cto.com/art/201007/210894.htm 熟悉三国的朋友都知道曹操,曹操有二十五个儿子,其中最得曹操宠爱的是曹丕.曹植.曹彰三个,曹丕性格阴冷, ...
- Discuz封锁蜘蛛最有效的方法
闲来无事翻代码,发现一个好东西,Discuz设计者考虑到了有些流氓搜索引擎不遵守roborts.txt,于是设计了一个NOROBOT变量,当这个变量为true 的时候,定义中的搜索引擎都会无法访问,默 ...
- java并发:简单面试问题集锦
多线程:Simultaneous Multithreading,简称SMT. 并行.并发 并行性(parallelism)指两个或两个以上的事件在同一时刻发生,在多道程序环境下,并行性使多个程序同一时 ...
- Bootstrap系列 -- 40. 导航条二级菜单
在导航条中添加二级菜单也非常简单 <div class="navbar navbar-default" role="navigation"> < ...
- Android开发之AutoCompleteTextView的简单使用
这里只谈简单的使用: 代码xml: <AutoCompleteTextView android:id="@+id/actv" android:layout_width=&qu ...
- DatePicker及其监听
xml文件: <DatePicker android:id="@+id/datep" android:layout_width="wrap_content" ...
- Python基础-字符串格式化_百分号方式_format方式
Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存.[PEP-3101] This ...