Codeforces 516D - Drazil and Morning Exercise(树的直径+并查集)
这是一道 jxd 的作业题,感觉难度不是特别大(虽然我并没有自己独立 AC,不过也可能是省选结束了我的脑子也没了罢(((,就随便写写罢
u1s1 这题似乎是 dreamoon 出的呢(
首先我们需求出 \(d_x\) 即 \(\max\limits_{y=1}^n\text{dist}(x,y)\),这个想怎么求怎么求,可以使用换根 \(dp\),也可以用树的直径,复杂度 \(\mathcal O(n)\)
求完之后该怎么做呢?注意到 \(q\) 很小,因此有一个很显然的想法是将所有点按 \(d\) 从小到大排序然后暴力双针+LCT,不过一来我不会 LCT,二来这样询问复杂度会达到 \(n\log n\),虽然应该可以通过,但并不优秀,因此我们暂时不讲这个做法。我们不妨来探究 \(d\) 的性质,记 \(r\) 为使 \(d_u\) 取到最小值的 \(u\),显然 \(u\) 在树的直径上,否则我们可以将其移到直径上并使得 \(d\) 值不会变得更大。
我们不妨以 \(r\) 为根将原先的无根树变成一棵有根树,那么有一个性质:对于任何 \(v\) 是 \(u\) 的祖先均有 \(d_v\ge d_u\)。证明:首先假设一条树的直径为 \(x,y\),我们先证明一个引理:对于任意节点 \(t\ne u\),记 \(ind_t\) 为使 \(\text{dist}(t,v)\) 取到最大值的 \(v\),那么 \(ind_t\) 一定不在 \(t\) 的子树中,考虑反证法,假设 \(ind_t\) 在 \(t\) 的子树中,那么一定有 \(d_r\ge \text{dist}(r,ind_t))>\text{dist}(t,ind_t)=d_t\),不符合 \(d_r\) 最小的条件,矛盾。显然原命题等价于对于所有 \(u\) 及其父亲 \(f\) 都有 \(d_f\le d_u\),考虑某个点 \(u\) 及其父亲 \(f\),若 \(f\ne r\),由于 \(ind_u\) 不在 \(u\) 的子树中,必然有 \(\text{dist}(ind_u,u)=\text{dist}(ind_u,f)+\text{dist}(u,f)\),又由于 \(ind_f\) 不在 \(f\) 的子树中,必然也有 \(ind_f\) 不在 \(u\) 的子树中,因此 \(\text{dist}(ind_u,f)=d_f\),又由于 \(\text(dist)(u,f)>0\),故 \(d_f<d_u\),否则由 \(d_r\) 为最小的 \(d_i\) 可知命题显然成立。
有了这个性质,我们可以用 two-pointers 的方法,枚举连通块中最小的 \(d_u\),并 two pointers 维护所有 \(d_u\le d_v\le d_u+l\) 的 \(v\),根据上面的推论在这样的 \(v\) 组成的子图中,\(u\) 所在的连通块必定是以 \(u\) 为根的一个虚树,并查集即可,虽然这里需要支持删点,看上去不太可做,不过显然删除的点并不会影响连通性,用并查集维护联通块大小是正确的。
时间复杂度 \(n\log n+qn\alpha(n)\)。
const int MAXN=1e5;
int n,hd[MAXN+5],to[MAXN*2+5],nxt[MAXN*2+5],val[MAXN*2+5],ec=0;
void adde(int u,int v,int w){to[++ec]=v;val[ec]=w;nxt[ec]=hd[u];hd[u]=ec;}
ll dis[MAXN+5],d[MAXN+5];
void dfs(int x,int f){
chkmax(d[x],dis[x]);
for(int e=hd[x];e;e=nxt[e]){
int y=to[e],z=val[e];if(y==f) continue;
dis[y]=dis[x]+z;dfs(y,x);
}
} int ord[MAXN+5],fa[MAXN+5];
void getfa(int x,int f){
fa[x]=f;
for(int e=hd[x];e;e=nxt[e]){
int y=to[e];if(y==f) continue;
getfa(y,x);
}
}
bool cmp(int x,int y){return d[x]<d[y];}
int f[MAXN+5],siz[MAXN+5];
int find(int x){return (!f[x])?x:f[x]=find(f[x]);}
void merge(int x,int y){x=find(x);y=find(y);if(x^y) f[x]=y,siz[y]+=siz[x];}
int main(){
scanf("%d",&n);
for(int i=1,u,v,w;i<n;i++){
scanf("%d%d%d",&u,&v,&w);
adde(u,v,w);adde(v,u,w);
} dfs(1,0);int rt=0;
for(int i=1;i<=n;i++) if(dis[i]>dis[rt]) rt=i;
dis[rt]=0;dfs(rt,0);rt=0;
for(int i=1;i<=n;i++) if(dis[i]>dis[rt]) rt=i;
dis[rt]=0;dfs(rt,0);for(int i=1;i<=n;i++) ord[i]=i;
sort(ord+1,ord+n+1,cmp);getfa(ord[1],0);
// for(int i=1;i<=n;i++) printf("%lld%c",d[i],(i==n)?'\n':' ');
// for(int i=1;i<=n;i++) printf("%d%c",ord[i],(i==n)?'\n':' ');
// for(int i=1;i<=n;i++) printf("%d%c",fa[i],(i==n)?'\n':' ');
int qu;scanf("%d",&qu);
while(qu--){
ll l;int ans=0;scanf("%lld",&l);
for(int i=1;i<=n;i++) f[i]=0,siz[i]=1;
for(int i=n,j=n;i;i--){
while(d[ord[j]]>d[ord[i]]+l) siz[find(ord[j])]--,j--;
// printf("%d %d %d\n",i,j,siz[find(ord[i])]);
chkmax(ans,siz[find(ord[i])]);if(fa[ord[i]]) merge(ord[i],fa[ord[i]]);
} printf("%d\n",ans);
}
return 0;
}
Codeforces 516D - Drazil and Morning Exercise(树的直径+并查集)的更多相关文章
- 【loj6038】「雅礼集训 2017 Day5」远行 树的直径+并查集+LCT
题目描述 给你 $n$ 个点,支持 $m$ 次操作,每次为以下两种:连一条边,保证连完后是一棵树/森林:询问一个点能到达的最远的点与该点的距离.强制在线. $n\le 3\times 10^5$ ,$ ...
- 【bzoj2870】最长道路tree 树的直径+并查集
题目描述 给定一棵N个点的树,求树上一条链使得链的长度乘链上所有点中的最小权值所得的积最大. 其中链长度定义为链上点的个数. 输入 第一行N 第二行N个数分别表示1~N的点权v[i] 接下来N-1行每 ...
- Codeforces 455C Civilization:树的直径 + 并查集【合并树后直径最小】
题目链接:http://codeforces.com/problemset/problem/455/C 题意: 给你一个森林,n个点,m条边. 然后有t个操作.共有两种操作: (1)1 x: 输出节点 ...
- 求树的直径+并查集(bfs,dfs都可以)hdu4514
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4514 这题主要是叫我们求出树的直径,在求树的直径之前要先判断一下有没有环 树的直径指的就是一棵树上面距 ...
- hdu 4514(树的直径+并查集)
湫湫系列故事——设计风景线 Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Tot ...
- loj6038「雅礼集训 2017 Day5」远行 树的直径+并查集+LCT
题目传送门 https://loj.ac/problem/6038 题解 根据树的直径的两个性质: 距离树上一个点最远的点一定是任意一条直径的一个端点. 两个联通块的并的直径是各自的联通块的两条直径的 ...
- Codeforces 437D The Child and Zoo - 树分治 - 贪心 - 并查集 - 最大生成树
Of course our child likes walking in a zoo. The zoo has n areas, that are numbered from 1 to n. The ...
- BZOJ 2870: 最长道路tree 树的直径+并查集
挺好的一道题. 把所有点都离线下来,一个个往里加入就行了. #include <cstdio> #include <algorithm> #define N 100003 #d ...
- [BZOJ3038]上帝造题的七分钟2 树状数组+并查集
考试的时候用了两个树状数组去优化,暴力修改,树状数组维护修改后区间差值还有最终求和,最后骗了40分.. 这道题有好多种做法,求和好说,最主要的是开方.这道题过的关键就是掌握一点:在数据范围内,最多开方 ...
随机推荐
- 运维常用python库&模块
sutil:是一个跨平台库(https://github.com/giampaolo/psutil)能够实现获取系统运行的进程和系统利用率(内存,CPU,磁盘,网络等),主要用于系统监控,分析和系统资 ...
- 并发编程从零开始(八)-ConcurrentHashMap
并发编程从零开始(八)-ConcurrentHashMap 5.5 ConcurrentHashMap HashMap通常的实现方式是"数组+链表",这种方式被称为"拉链 ...
- Seata整合SpringBoot和Mybatis
Seata整合SpringBoot和Mybatis 一.背景 二.实现功能 三.每个服务使用到的技术 1.账户服务 2.订单服务 四.服务实现 1.账户服务实现 1.引入jar包 2.项目配置 3.建 ...
- Java High Level REST Client 使用地理位置查询
Java High Level REST Client 使用地理位置查询 一.需求 二.对应的query语句 三.对应java代码 1.引入 jar 包 2.创建 RestHighLevelClien ...
- openmp学习心得(一)
主要在vs2015下使用OMP,写一些自己omp的学习心得: 一.在VS2015下OpenMP的使用: 1.VS2015也仅仅支持OpenMP2.0版本,VS对OpenMP的支持并不太好. 2.在VS ...
- 21.10.18 test
可可大神出题,四款有趣的游戏推荐,第四个好玩/se T1 loopers \(\color{green}{100}\) 考虑钦定 \(a_1,a_i\) 的位置,固定左边一坨,那么剩下的一坨的 \(\ ...
- python re:正向肯定预查(?=)和反向肯定预查(?<=)
参考资料:https://tool.oschina.net/uploads/apidocs/jquery/regexp.html (?=pattern) 正向肯定预查,在任何匹配pattern的字符串 ...
- VIVADO 2017.4配置MIG IP注意事项
1.2GB的single rank SODIMMs配置pin还是和以前一样没有问题: 2.8GB SODIMMs配置pin需要注意4点: (1).所有的DDR3引脚都需要在连续的BANK上,例如Z71 ...
- Codeforces Round #742 (Div. 2)题解
链接 \(A,B\)题签到,就完了. \(C\)题,考虑进位时多进一位,由于是隔一位进的,所以可以发现奇数位和偶数位是相互独立的,那么我们就把奇数位和偶数位单独拉出来组成数字例如:34789,我们单独 ...
- linux 内核源代码情景分析——几个重要的数据结构和函数
页面目录PGD.中间目录PMD和页面表PT分别是由表项pgd_t.pmd_t和pte_t构成的数组,而这些表项都是数据结构 1 /* 2 * These are used to make use of ...