题目链接:

[JOI 2019 Final]独特的城市

对于每个点,它的答案最大就是与它距离最远的点的距离。

而如果与它距离为$x$的点有大于等于两个,那么与它距离小于等于$x$的点都不会被计入答案。

所以我们需要找到对于每个点$u$距离它最远的点及最小的距离$x$满足距离$u$的距离大于等于$x$的点都只有一个。

那么怎么找距离每个点最远的点?

这个点自然就是树的直径的一个端点了!

我们将树的直径先找到,然后讨论一下对于每个点,有哪些点可能会被计入答案:

如图所示,我们以点$x$为例,假设它距离直径两端点中的$S$较近($y$为$x$距离直径上最近的点),设$dis$代表两点距离:

对于$y$左边点所有点,显然$S$与$y$的距离最远,但$dis(S,y)<dis(T,y)$,所以$y$左边的所有点都不会被计入答案。

对于在$x$子树中的点,他们与$x$的距离要小于$dis(y,T)$,也就小于$dis(x,T)$,所以不会被计入答案。

对于在$y$子树中但不在$x$子树中的点(例如$b$),因为$dis(y,b)\le dis(y,S)$,所以$dis(b,d)<dis(S,d)$,不会被计入答案。

对于$y$与$T$之间的点的子树中的点(例如$c$),显然$dis(y,c)\le dis(y,T)$,所以这类点不会被计入答案。

那么综上所述对于靠近$S$的点,只有$x$到$T$之间的点才有可能被计入答案,对于靠近$T$的点同理。

所以我们只需要分别以$S$和$T$为根遍历整棵树,用一个单调栈保存每个点到根的这条链上能被计入答案的点即可。

求不同权值个数,再开一个桶记录栈中每种权值的个数,每次进栈或弹栈时对应加减。

因为答案与深度有关,我们将原树长链剖分。

对于每个点,当走重儿子时,求出所有轻儿子的子树中的最长链长度$len$,将当前栈中与$x$距离小于等于$len$的点弹出;当遍历轻儿子时,将当前栈中与$x$距离小于等于$x$往下最长链长度的点弹出。

注意要在弹栈之后再把$x$压入栈中,而且遍历每个儿子前都要重新将$x$压入栈中。

最后将以$S$为根时的答案与以$T$为根时的答案取最大值即可。

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int head[200010];
int to[400010];
int dep[200010];
int next[400010];
int mx[200010];
int son[200010];
int st[200010];
int top;
int tot;
int S,T;
int res;
int ans[200010];
int n,m;
int x,y;
int col[200010];
int cnt[200010];
void add(int x,int y)
{next[++tot]=head[x];head[x]=tot;to[tot]=y;
}
void pop()
{cnt[col[st[top]]]--;res-=(cnt[col[st[top]]]==0);top--;
}
void push(int x)
{st[++top]=x;cnt[col[x]]++;res+=(cnt[col[x]]==1);
}
void dfs(int x,int fa)
{dep[x]=dep[fa]+1;for(int i=head[x];i;i=next[i]){if(to[i]!=fa){dfs(to[i],x);}}
}
void dfs1(int x,int fa)
{son[x]=0;mx[x]=0;dep[x]=dep[fa]+1;for(int i=head[x];i;i=next[i]){if(to[i]!=fa){dfs1(to[i],x);if(mx[to[i]]>mx[son[x]]){son[x]=to[i];}}}mx[x]=mx[son[x]]+1;
}
void dfs2(int x,int fa)
{if(!son[x]){ans[x]=max(ans[x],res);return ;}int len=0;for(int i=head[x];i;i=next[i]){if(to[i]!=fa&&to[i]!=son[x]){len=max(len,mx[to[i]]);}}while(top&&dep[st[top]]>=dep[x]-len){pop();}push(x);dfs2(son[x],x);for(int i=head[x];i;i=next[i]){if(to[i]!=fa&&to[i]!=son[x]){while(top&&dep[st[top]]>=dep[x]-mx[son[x]]){pop();}push(x);dfs2(to[i],x);}}while(top&&dep[st[top]]>=dep[x]-mx[son[x]]){pop();}ans[x]=max(ans[x],res);
}
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<n;i++){scanf("%d%d",&x,&y);add(x,y);add(y,x);}for(int i=1;i<=n;i++){scanf("%d",&col[i]);}dfs(1,0);for(int i=1;i<=n;i++){S=dep[i]>dep[S]?i:S;}dfs(S,0);for(int i=1;i<=n;i++){T=dep[i]>dep[T]?i:T;}dfs1(S,0);dfs2(S,0);dfs1(T,0);dfs2(T,0);for(int i=1;i<=n;i++){printf("%d\n",ans[i]);}
}

转载于:https://www.cnblogs.com/Khada-Jhin/p/10761750.html

[LOJ3014][JOI 2019 Final]独特的城市——树的直径+长链剖分相关推荐

  1. P3899 [湖南集训]更为厉害(线段树合并、长链剖分、二维数点)

    P3899 [湖南集训]更为厉害 若 deepb<deepa\text{deep}_b<\text{deep}_adeepb​<deepa​:c 在点 a 的子树中,根据乘法原理计算 ...

  2. [十二省联考2019]春节十二响——长链剖分+堆

    题目链接: [十二省联考2019]春节十二响 可以发现每条链上的所有点都要放在不同的段里,那么最多只需要树的深度这么多段就够了. 因为这样可以保证每条链上的点可以放在不同的段中而且一个点放在这些段中一 ...

  3. 对LCA、树上倍增、树链剖分(重链剖分长链剖分)和LCT(Link-Cut Tree)的学习

    LCA what is LCA & what can LCA do LCA(Lowest Common Ancestors),即最近公共祖先 在一棵树上,两个节点的深度最浅的公共祖先就是 L ...

  4. Bzoj4016/洛谷P2993 [FJOI2014] 最短路径树问题(最短路径问题+长链剖分/点分治)

    题面 Bzoj 洛谷 题解 首先把最短路径树建出来(用\(Dijkstra\),没试过\(SPFA\)\(\leftarrow\)它死了),然后问题就变成了一个关于深度的问题,可以用长链剖分做,所以我 ...

  5. 【十二省联考2019】希望【点边容斥】【换根dp】【长链剖分】【线性数据结构】【回退数据结构】【离线逆元】

    题意:给一棵树,两个参数 k,Lk,Lk,L,需要选择 kkk 个连通块,使得这 kkk 个连通块存在一个公共点,且该公共点到 kkk 个连通块内的任意一点的距离不超过 LLL,求方案数 模 9982 ...

  6. YBTOJ:最短时间(长链剖分、线段树)

    解析 不难得到最优策略:先尽可能的快的送死直到路径畅通无组,然后一口气冲到t点. 现在的难点就在于如何尽可能的快的送掉特定的次数. 不难发现,花费时间关于死亡次数的函数必然是一个下凸包. 设 fx,i ...

  7. UOJ#284-快乐游戏鸡【长链剖分,线段树】

    正题 题目链接:https://uoj.ac/problem/284 题目大意 nnn个点的一棵树,每个点有一个wiw_iwi​表示至少死亡wiw_iwi​次才能通过这个点,否则就会死亡.只能往子节点 ...

  8. 树链剖分之长链剖分 详解 题目整理

    树链剖分 题目中出现的树链剖分一般分为两种,重链剖分和长链剖分 重链剖分:选择子树最大的儿子, 将其归入当前点所在 的同一条重链 长链剖分:选择向下能达到的深 度最深的儿子,将其归 入当前点所在的同一 ...

  9. $Loj10155$ 数字转换(求树的最长链) 树形$DP$

    loj Description 如果一个数x的/约数和/y(不包括他本身)比他本身小,那么x可以变成y,y 也可以变成x.限定所有数字变换在不超过n的正整数范围内进行,求不断进行数字变换且不出现重复数 ...

最新文章

  1. html网页钩子,HTML5中的meta标签 和 IE浏览器能识别的钩子
  2. python的基本语法数据类型有那些_python语法基础(基本数据类型)
  3. js控制a标签点击事件 触发下载
  4. git merge 回退_Git 基础学习总结2(学不会你锤我)
  5. leetcode 买卖股票的最佳时机 II
  6. 俄罗斯调查PC厂商合谋操纵市场 联想被指妨碍调查
  7. 常用加密算法概述、比较及使用场景说明
  8. 江苏省计算机c语言考试题库,2020上半年江苏省计算机等级考试辅导教程:二级C语言上机考试题库...
  9. kafka和mqtt的区别和联系
  10. 浪人下载和浪人文章的漏洞利用
  11. 什么是远程桌面?花生壳+Windows远程桌面控制教程
  12. cad连筋字体怎么安装_天正建筑CAD字体太小怎么办?别慌!问题不大,解决方案都在这里...
  13. QT版用QLCDnumber显示时间
  14. 2014网络红人照片网络红人排行榜2014经典语录网络红人斌少
  15. mui 图片预览(3)
  16. python输出偶数_如何用Python 判断奇偶数
  17. python中怎么打印出表格_怎么使用python脚本实现表格打印?
  18. python之测试类
  19. 灰度图像--形态学处理:腐蚀、膨胀、开操作、闭操作、顶帽、底帽等
  20. 风控基础——风控模型、规则、策略的区别

热门文章

  1. 新手如何开始学习3D建模?美术基础重不重要?
  2. mysql 插入毫秒数据_【转载】怎样在mybatis里向mysql中插入毫秒数的时间?
  3. 【TensorFlow】TensorFlow函数精讲之tf.train.ExponentialMovingAverage()
  4. 基于注意力机制的seq2seq网络
  5. tensorflow的数据输入
  6. 文本数据处理的终极指南-[NLP入门]
  7. 数据结构(三)插入排序
  8. ivx中字体显示_html-中文字体在CSS中的显示(Unicode编码)(转载)
  9. mysql 为了检索从某一个偏移量到记录集的结束所有的记录行_mysql limit 效率分析...
  10. java项目_好程序员Java分享从入门到服务端项目开发的过程