【Tsinsen-A1486】树(王康宁) 点分治 + Trie
A1486. 树(王康宁)
接下来一行N个整数,每个数均为0或1,小A喜欢第i个点当且仅当这一行的第i个数是1。
接下来一行N个整数V1, V2, …, VN,其中第i个数表示第i个点的权值。
最后N-1行,每行两个整数u, v,表示树的一条边。
1 1 1
0 4 7
1 2
2 3
1 0 1
3 5 6
1 2
2 3
1 1 1 1
10 10 10 10
1 2
1 3
1 4
测试点标号 | N的范围 | K的范围 | Vi的范围 | 其它特点 |
1 | N=2 | K=0 | ||
2 | N≤10 | |||
3 | N≤1000 | 这棵树是一条链 | ||
4 | N≤1000 | K=0 | 这棵树是一条链 | |
5 | N≤4000 | |||
6 | N≤30000 | K=0 | Vi≤7 | |
7 | N≤40000 | K=0 | ||
8 | N≤40000 | K=0 | ||
9 | N≤50000 | K=0 | 这棵树是一条链 | |
10 | N≤50000 | K=0 | ||
11 | N≤60000 | Vi≤7 | ||
12 | N≤60000 | 这棵树是一条链 | ||
13 | N≤70000 | Vi≤107 | ||
14 | N≤70000 | Vi≤107 | ||
15 | N≤80000 | |||
16 | N≤80000 | |||
17 | N≤90000 | |||
18 | N≤90000 | |||
19 | N≤100000 | |||
20 | N≤100000 |
对于100%的数据,1≤N≤100000, 0≤K≤N, 0≤Vi≤109, 保证输入的是一棵合法的树.
Solution
这道题,先考虑弱化版本..
如果$K=0$不考虑经过关键点的数量,非常简单。
可以直接从根dfs一遍得到到所有节点的xor和,然后全部插入Trie中,再枚举每个点贪心在Trie上跑即可,复杂度$O(NlogN)$。
但是这个题需要限制经过节点数,就必须点分治+Trie贪心,时间复杂度$O(Nlog^{2}N)$。
最普通的想法就是对于经过不同的关键点的路径xor和分别建一棵Trie树,然后查询的时候查询即可,但是$K$上限过大。
所以考虑维护一棵Trie树,在每个节点上维护一下经过的关键点数,在贪心统计答案的时候处理一下即可。
这里有一个问题,就是处理一棵子树的时候,最顶部的节点会重复计算,所以可以考虑先不计算它的影响,在统计答案的时候再计算回来。
Code
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
inline int read()
{
int x=0,f=1; char ch=getchar();
while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
#define MAXN 100010 int N,K,lov[MAXN],c[MAXN],ans=-1; struct EdgeNode{
int next,to;
}edge[MAXN<<1];
int head[MAXN],cnt=1;
inline void AddEdge(int u,int v) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;}
inline void InsertEdge(int u,int v) {AddEdge(u,v); AddEdge(v,u);} namespace Trie{
int son[MAXN][2],sz,d[MAXN];
int s[32];
inline void Calc(int x) {memset(s,0,sizeof(s)); for (int t=31; t>=0; t--) s[t]=(x>>t)&1;}
inline void Clear() {son[1][0]=son[1][1]=0; sz=1;}
inline void Insert(int x,int dep)
{
int now=1;
Calc(x);
for (int i=31; i>=0; i--)
if (son[now][s[i]]) now=son[now][s[i]],d[now]=max(d[now],dep);
else son[now][s[i]]=++sz,now=sz,son[now][1]=son[now][0]=0,d[now]=dep;
}
inline int Query(int x,int dep)
{
int now=1,mx=0;
Calc(x);
for (int i=31; i>=0; i--) {
if (son[now][s[i]^1] && d[son[now][s[i]^1]]>=dep) now=son[now][s[i]^1],mx|=(1<<i);
else if (son[now][s[i]] && d[son[now][s[i]]]>=dep) now=son[now][s[i]];
else return -1;
}
return mx;
}
}using namespace Trie; namespace TreeDivide{
int size[MAXN],mx[MAXN],Sz,root;
bool visit[MAXN];
struct Node{
int x,y;
Node (int X=0,int Y=0) {x=X,y=Y;}
}stack[MAXN];
int top;
inline void Getroot(int now,int last)
{
size[now]=1,mx[now]=0;
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].to!=last && !visit[edge[i].to]) {
Getroot(edge[i].to,now);
size[now]+=size[edge[i].to];
mx[now]=max(mx[now],size[edge[i].to]);
}
mx[now]=max(mx[now],Sz-size[now]);
if (mx[now]<mx[root]) root=now;
}
inline void DFS(int now,int last,int dep,int val,int fav)
{
ans=max(ans,Query(val^fav,K-dep));
stack[++top]=Node(val,dep);
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].to!=last && !visit[edge[i].to]) {
DFS(edge[i].to,now,dep+lov[edge[i].to],val^c[edge[i].to],fav);
}
}
inline void Divide(int now)
{
// printf("root=%d\n",now);
visit[now]=1;
Trie::Clear();
K-=lov[now];
if (K<=0) ans=max(ans,c[now]);
for (int i=head[now]; i; i=edge[i].next)
if (!visit[edge[i].to]) {
top=0;
DFS(edge[i].to,now,lov[edge[i].to],c[edge[i].to],c[now]);
for (int j=1; j<=top; j++)
Trie::Insert(stack[j].x,stack[j].y);
}
K+=lov[now];
for (int i=head[now]; i; i=edge[i].next)
if (!visit[edge[i].to]) {
root=0;
Sz=size[edge[i].to];
Getroot(edge[i].to,now);
Divide(root);
}
}
}using namespace TreeDivide; int main()
{
N=read(),K=read();
for (int i=1; i<=N; i++) lov[i]=read();
for (int i=1; i<=N; i++) c[i]=read();
for (int i=1,x,y; i<=N-1; i++) x=read(),y=read(),InsertEdge(x,y);
mx[root=0]=Sz=N;
Getroot(1,0);
Divide(root);
printf("%d\n",ans);
return 0;
}
【Tsinsen-A1486】树(王康宁) 点分治 + Trie的更多相关文章
- Tsinsen A1486. 树(王康宁)
Description 一棵树,问至少有 \(k\) 个黑点的路径最大异或和. Sol 点分治. 用点分治找重心控制树高就不说了,主要是对答案的统计的地方. 将所有路径按点的个数排序. 可以发现当左端 ...
- 【BZOJ4016】[FJOI2014]最短路径树问题(点分治,最短路)
[BZOJ4016][FJOI2014]最短路径树问题(点分治,最短路) 题面 BZOJ 洛谷 题解 首先把最短路径树给构建出来,然后直接点分治就行了. 这个东西似乎也可以长链剖分,然而没有必要. # ...
- A1486. 树(王康宁)
题目:http://www.tsinsen.com/A1486 题解: 其实看到和路径有关的就应该想到点分治. 我们找出重心之后遍历每一棵子树得到它的 { x=经过特殊点的个数,y=到rt的异或和} ...
- 【xsy1122】 路径 点分治+trie
题目大意:给你一棵n个点的树,树边上有边权,对于每一个点,你要求出经过该点的所有的路径中,路径异或和最大的值. 数据范围:$n≤10^5$,边权$≤10^9$. 我们考虑枚举每一条路径,显然这个是会T ...
- Tsinsen A1493 城市规划(DP + CDQ分治 + NTT)
题目 Source http://www.tsinsen.com/A1493 Description 刚刚解决完电力网络的问题, 阿狸又被领导的任务给难住了. 刚才说过, 阿狸的国家有n个城市, 现在 ...
- 【BZOJ-3648】寝室管理 环套树 + 树状数组 + 点分治
3648: 寝室管理 Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 239 Solved: 106[Submit][Status][Discuss] ...
- 【BZOJ-2229】最小割 最小割树(最大流+分治)
2229: [Zjoi2011]最小割 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 1565 Solved: 560[Submit][Status ...
- Tsinsen A1505. 树(张闻涛) 倍增LCA,可持久化线段树,DFS序
题目:http://www.tsinsen.com/A1505 A1505. 树(张闻涛) 时间限制:1.0s 内存限制:512.0MB 总提交次数:196 AC次数:65 平均分: ...
- Codeforces 888G(分治+trie)
按位贪心,以当前考虑位是0还是1将数分成两部分,则MST中这两部分之间只会存在一条边,因为一旦有两条或以上的边,考虑两条边在原图中所成的环,显然这两条边有一条是环上的权值最大边,不会出现在MST中.则 ...
随机推荐
- 原生JS不到30行,实现类似javascript MVC的功能-minTemplate
严格来讲不能说是MVC,应为模版里不能写逻辑语句. 灵感来源于我的上篇文字:<封装JSON数据转自定义HTML方法parseHTML>: 这里再封装一个简单方法,在保持原来的方便改变不大的 ...
- AngularJs -- 指令简介
整理书籍内容(QQ:283125476 发布者:M [重在分享,有建议请联系->QQ号]) HTML文档 HTML文档是一个纯文本文件,包含了页面的结构以及由CSS定义的样式,或者可以操作样式的 ...
- Zookeeper集群 + Kafka集群 + KafkaOffsetMonitor 监控
一.Zookeeper ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用提供一 ...
- SQLSTATE[42000]
SQLSTATE[42000]: Syntax error or access violation: 1140 Mixing of GROUP columns (MIN(),MAX(),COUNT() ...
- 第11月第11天 avplayer循环播放
1. /* Setting actionAtItemEnd to None prevents the movie from getting paused at item end. A very sim ...
- 第7月第20天 epoll
1. ) { struct sockaddr in_addr; socklen_t in_len; int infd; char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; ...
- [译]How To Use the Linux Auditing System on CentOS 7
本文是How To Use the Linux Auditing System on CentOS 7的中文版,翻译不到之处,还请指出和多多包涵.本文并不会完全遵从原文的一些格式,而是加入自己学习的理 ...
- vb 中recordset提示对象关闭时不允许操作
vb中执行查询后,一般要判断是否为空,只要执行的查询执行了select,都可以用rs.eof 或者 rs.recordcount来判断, 但是,如果执行的sql中加了逻辑判断,导致没有执行任何sele ...
- Redis的五大数据类型
1.String(字符串) String是Redis最基本的类型,一个Key对应一个Value. String类型是二进制安全的,意思是Redis的String可以包含任何数据,比如jpg图片或者序列 ...
- nginx安装报错:configure: error: the HTTP rewrite module requires the PCRE library
参考:http://blog.51cto.com/williamx/958398 需要安装pcre-devel与openssl-devel yum -y install pcre-devel open ...