Codeforces 题目传送门 & 洛谷题目传送门

这是一道 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(树的直径+并查集)的更多相关文章

  1. 【loj6038】「雅礼集训 2017 Day5」远行 树的直径+并查集+LCT

    题目描述 给你 $n$ 个点,支持 $m$ 次操作,每次为以下两种:连一条边,保证连完后是一棵树/森林:询问一个点能到达的最远的点与该点的距离.强制在线. $n\le 3\times 10^5$ ,$ ...

  2. 【bzoj2870】最长道路tree 树的直径+并查集

    题目描述 给定一棵N个点的树,求树上一条链使得链的长度乘链上所有点中的最小权值所得的积最大. 其中链长度定义为链上点的个数. 输入 第一行N 第二行N个数分别表示1~N的点权v[i] 接下来N-1行每 ...

  3. Codeforces 455C Civilization:树的直径 + 并查集【合并树后直径最小】

    题目链接:http://codeforces.com/problemset/problem/455/C 题意: 给你一个森林,n个点,m条边. 然后有t个操作.共有两种操作: (1)1 x: 输出节点 ...

  4. 求树的直径+并查集(bfs,dfs都可以)hdu4514

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4514 这题主要是叫我们求出树的直径,在求树的直径之前要先判断一下有没有环 树的直径指的就是一棵树上面距 ...

  5. hdu 4514(树的直径+并查集)

    湫湫系列故事——设计风景线 Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Tot ...

  6. loj6038「雅礼集训 2017 Day5」远行 树的直径+并查集+LCT

    题目传送门 https://loj.ac/problem/6038 题解 根据树的直径的两个性质: 距离树上一个点最远的点一定是任意一条直径的一个端点. 两个联通块的并的直径是各自的联通块的两条直径的 ...

  7. 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 ...

  8. BZOJ 2870: 最长道路tree 树的直径+并查集

    挺好的一道题. 把所有点都离线下来,一个个往里加入就行了. #include <cstdio> #include <algorithm> #define N 100003 #d ...

  9. [BZOJ3038]上帝造题的七分钟2 树状数组+并查集

    考试的时候用了两个树状数组去优化,暴力修改,树状数组维护修改后区间差值还有最终求和,最后骗了40分.. 这道题有好多种做法,求和好说,最主要的是开方.这道题过的关键就是掌握一点:在数据范围内,最多开方 ...

随机推荐

  1. Python爬虫:给我一个链接,快手视频随便下载

    前言 讲一下,文明爬虫,从我做起(1.文章中的程序代码仅供学习,切莫用于商业活动,一经被相关人员发现,本小编概不负责!2.请在服务器闲时运行本程序代码,以免对服务器造成很大的负担.) 1. 实现原理 ...

  2. UML快速概述 - All you need to know about UML

    UML 是统一建模语言的缩写,就像使用一组图表来可视化软件建模的蓝图(或设计计划).它不仅可以让您彻底评估整个概念,还可以确保团队中的每个人都在同一页面上.   UML 图可以组织成两个不同的组. 结 ...

  3. echart3 力引导布局实现节点的提示和折叠

    最近在项目中需要开发一个图表来显示人员的各种属性,类似于一种树形的结构进行显示数据.如果多个人员有同一个属性,那么需要将相同的属性进行连线,即关联起来.即形成一个关系图,由于我自身对echarts稍微 ...

  4. set prompt = "任意匹配字符" 当前目录详解

    转载:https://blog.csdn.net/alexdream/article/details/6865730 研究了两天的FreeBSD,总是感觉输入提示符那里怪怪的,而且默认的提示符还不带显 ...

  5. Memory Analyzer Tool 使用

    转载出处:https://wensong.iteye.com/blog/1986449 最近一段时间一直在研究热部署,热部署中涉及到一个比较头痛的问题就是查内存泄露(Memory Leak),于是乎在 ...

  6. Linux的inode与block

    1,inode包含文件的元信息,具体来说有以下内容: 文件的字节数 文件拥有者的User ID 文件的Group ID 文件的读.写.执行权限 文件的时间戳,共有三个:ctime指inode上次文件属 ...

  7. notepad++ 替换回车换行

    以" | "为分隔符,换行 结果如下图:

  8. You (oracle) are not allowed to access to (crontab) because of pam configura

    用oracle用户添加备份计划任务,crontab -e,提示:You (oracle) are not allowed to access to (crontab) because of pam c ...

  9. 攻防世界 Misc 新手练习区 坚持60s Writeup

    攻防世界 Misc 新手练习区 坚持60s Writeup 题目介绍 题目考点 java反编译 jd-gui 的使用 Writeup 下载附件并打开 kali执行命令 java -jar 9dc125 ...

  10. React + 导入模块的一个错误

    导入模块的时候出现这个错误: Attempted import error: 'd3' does not contain a default export (imported as 'd3'). 把导 ...