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. 手把手教你学Dapr - 2. 必须知道的概念

    Sidecar 边车 Dapr API提供Http和gRPC两种通讯方式. 运行方式则可以是容器也可以是进程(Windows开发推荐使用Self Hosted,后续会解释). 这样的好处是与运行环境无 ...

  2. 热身训练1 ping ping ping

    点此进入 题意: 一棵树,n+1 个节点,以0号节点为根,给出端点(a,b),节点a到节点b的路径上,至少有一个点是"坏掉的",求"坏掉的点"最少 分析: St ...

  3. [火星补锅] 非确定性有穷状态决策自动机练习题Vol.1 T3 第K大区间 题解

    前言: 老火星人了 解析: 很妙的二分题.如果没想到二分答案.. 很容易想到尝试用双指针扫一下,看看能不能统计答案. 首先,tail指针右移时很好处理,因为tail指针右移对区间最大值的影响之可能作用 ...

  4. 多边形——————区间dp

    原题链接:https://www.acwing.com/problem/content/285/ 题意简单来说就是:给你一个环,断掉一条边使其成为一个链,用这个链跑dp,求最大得分. 首先这不是一道板 ...

  5. Python基础——数据类型——字符串

    整数.浮点数.布尔值的用法大同小异,而Python字符串的一些用法不易记住,这里以廖雪峰教程为基础,进行一些思考和复习总结. 字符串是什么? 以单引号'或者双引号"括起来的任意文本,比如:& ...

  6. 构建乘积数组 牛客网 剑指Offer

    构建成绩数组 牛客网 剑指Offer 题目描述 给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1],其中B中的元素B[i]=A[0]A[1]...*A[i-1]A[i ...

  7. Netfilter和iptables介绍

    前言 在开始Kubernetes的网络之前我们先来学习Netfilter,Netfilter可能了解的人比较少,但是iptables用过 Linux的都应该知道.本文主要介绍Netfilter与ipt ...

  8. vue-router 4 你真的熟练吗?

    虽然 vue-router 4 大多数 API 保持不变,但是在 vue3 中以插件形式存在,所以在使用时有一定的变化.接下来就学习学习它是如何使用的. 一.安装并创建实例 安装最新版本的 vue-r ...

  9. pip 安装使用 ImportError: No module named setuptools 解决方法

    安装过程详见这篇博客: http://www.ttlsa.com/python/how-to-install-and-use-pip-ttlsa/ 安装后运行到:python setup.py ins ...

  10. cpu内核态与用户态

    1.操作系统需要两种CPU状态 内核态(Kernel Mode):运行操作系统程序,操作硬件 用户态(User Mode):运行用户程序 2.指令划分 特权指令:只能由操作系统使用.用户程序不能使用的 ...