loj 3014「JOI 2019 Final」独特的城市
我本来是直接口胡了一个意思一样的做法的,但是因为觉得有点假+实现要用并查集(?)就卡了好一会儿...
对于一个点\(x\)来说,独特的点一定在它的最长链上,如果有独特的点不在最长链上,那么最长链上一定有和他到\(x\)距离相同的点,矛盾
然后对于一个点,最长链端点一定可以是直径的两端点之一,所以如果我们分别以树的直径的两端点为根进行dfs,那么一个点在其中一次dfs中,独特的点都会在到根的路径上,所以我们用栈维护到根的点,然后不同颜色数开桶来维护,每次压栈或弹栈时改变桶内元素个数,然后根据某个桶元素变化维护当前答案
然后在点\(x\)到根的路径上,其他挂出去的多余的链会往上覆盖掉一些点(也就是覆盖掉到\(x\)距离为某个值的点,它们不是独特的),导致这些点不能贡献答案.所以在dfs进别的子树时要用这些没用到的链来删掉一些点.具体来讲,dfs某个点时把父亲压入栈;在之前先预处理一个点子树内最长链长度以及次长链长度(最长链次长链要来自不同子树),然后先把到\(x\)距离\(\le\)次长链长度的栈里的点弹掉,递归处理最长链所在子树,再把到\(x\)距离\(\le\)最长链长度的栈里的点弹掉,这个时候维护的颜色种数就是当前这个点的答案,可以直接更新答案,之后递归其他子树处理.每个点答案为两个直径端点算出的值的max
#include<bits/stdc++.h>
#define LL long long
#define uLL unsigned long long
#define db double
using namespace std;
const int N=2e5+10;
int rd()
{
int x=0,w=1;char ch=0;
while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
int to[N<<1],nt[N<<1],hd[N],tot=1;
void add(int x,int y)
{
++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot;
++tot,to[tot]=x,nt[tot]=hd[y],hd[y]=tot;
}
int n,m,an[N],a[N],mx,r1,r2;
void dd(int x,int ffa,int de)
{
if(mx<de) mx=de,r2=x;
for(int i=hd[x];i;i=nt[i])
{
int y=to[i];
if(y==ffa) continue;
dd(y,x,de+1);
}
}
int de[N],dp[N],dp2[N],hs[N],stk[N],tp,bk[N],na;
void dfs1(int x,int ffa)
{
hs[x]=dp[x]=dp2[x]=0;
if(ffa&&!nt[hd[x]]){dp[x]=de[x];return;}
for(int i=hd[x];i;i=nt[i])
{
int y=to[i];
if(y==ffa) continue;
de[y]=de[x]+1,dfs1(y,x);
if(dp[y]>=dp[x]) hs[x]=y,dp2[x]=dp[x],dp[x]=dp[y];
else if(dp[y]>=dp2[x]) dp2[x]=dp[y];
}
}
void dfs3(int x,int ffa)
{
if(ffa) stk[++tp]=ffa,na+=!bk[a[ffa]],++bk[a[ffa]];
if(!hs[x]) an[x]=max(an[x],na);
else
{
while(tp&&de[x]-de[stk[tp]]<=dp2[x]-de[x])
--bk[a[stk[tp]]],na-=!bk[a[stk[tp]]],--tp;
dfs3(hs[x],x);
while(tp&&de[x]-de[stk[tp]]<=dp[x]-de[x])
--bk[a[stk[tp]]],na-=!bk[a[stk[tp]]],--tp;
an[x]=max(an[x],na);
for(int i=hd[x];i;i=nt[i])
{
int y=to[i];
if(y==ffa||y==hs[x]) continue;
dfs3(y,x);
}
}
if(ffa&&stk[tp]==ffa) --bk[a[ffa]],na-=!bk[a[ffa]],--tp;
}
void wk(int rt)
{
de[rt]=0,dfs1(rt,0);
dfs3(rt,0);
}
int main()
{
n=rd(),m=rd();
for(int i=1;i<n;++i) add(rd(),rd());
for(int i=1;i<=n;++i) a[i]=rd();
mx=-1,dd(1,0,0),r1=r2;
mx=-1,dd(r1,0,0);
wk(r1),wk(r2);
for(int i=1;i<=n;++i) printf("%d\n",an[i]);
return 0;
}
loj 3014「JOI 2019 Final」独特的城市的更多相关文章
- 【LOJ】#3014. 「JOI 2019 Final」独特的城市(长链剖分)
LOJ#3014. 「JOI 2019 Final」独特的城市(长链剖分) 显然我们画一条直径,容易发现被统计的只可能是直径某个距离较远的端点到这个点的路径上的值 用一个栈统计可以被统计的点,然后我们 ...
- LOJ#2351. 「JOI 2018 Final」毒蛇越狱
LOJ#2351. 「JOI 2018 Final」毒蛇越狱 https://loj.ac/problem/2351 分析: 首先有\(2^{|?|}\)的暴力非常好做. 观察到\(min(|1|,| ...
- LOJ#2764. 「JOI 2013 Final」JOIOI 塔
题目地址 https://loj.ac/problem/2764 题解 真的想不到二分...不看tag的话... 考虑二分答案转化为判定问题,那么问题就变成了能不能组合出x个JOI/IOI,考虑贪心判 ...
- LOJ#2343. 「JOI 2016 Final」集邮比赛 2
题目地址 https://loj.ac/problem/2343 题解 首先处理出\(f[i]\)表示以当前位置开头(J,O,I)的合法方案数.这个显然可以\(O(n)\)处理出来.然后考虑在每个位置 ...
- loj 2759「JOI 2014 Final」飞天鼠
loj 这题有在一棵树上上升或者下降的操作,稍加分析后可以发现上升操作如果不是一定要做(指高度不足以到下一棵树或者是最后到达\(n\))就不做,下降操作也是如果不是一定要做(指到达下一棵树时高度过高) ...
- loj 2336「JOI 2017 Final」绳
loj 首先,所有位置最多被染色一次,因为要染多次的话,还不如一开始就染成最终的颜色.并且你可以一开始就染好色 因为最终长度为2,那么如果染完后这个序列可以被折完,那么首先最多只有两种颜色,还有就是要 ...
- 「JOI 2019 Final」 硬币收藏
题目链接 戳我 \(Solution\) 先将所有棋子移动到最近的目标点上 我们设两个变量\(ans1,ans2\)表示到目前为止这个点上可以移动棋子的数目,然后\(f[i][j]\)表示\((i,j ...
- loj#2334 「JOI 2017 Final」JOIOI 王国
分析 二分答案 判断左上角是否满足 为了覆盖所有范围 我们依次把右下角,左上角,右上角移动到左上角 代码 #include<bits/stdc++.h> using namespace s ...
- loj#2333 「JOI 2017 Final」准高速电车
分析 我们发现到达一个点一定是先快车再准快车再慢车 于是快车将1-n分为多个区间 每次取出每个区间当前能到达的点的数量 选剩余时间贡献最大的的一个取得贡献并且再能到达的最远点建立准快车 代码 #inc ...
随机推荐
- PCB Layout初学者必会知识总结(转)
PCB是印刷电路板(即Printed Circuit Board)的简称.印刷电路板是组装电子零件用的基板,是在通用基材上按预定设计形成点间连接及印制元件的印制板.该产品的主要功能是使各种电子零组件形 ...
- 【Makefile】Makefile中的赋值符号=、:=、?=、+=
Makefile中主要有四个赋值符号: = 是最基本的赋值:= 是覆盖之前的值?= 是如果没有被赋值过就赋予等号后面的值+= 是添加等号后面的值 1.“=” “=”赋值:make会将整个makefil ...
- flutter 自定义tabbar 给tabbar添加背景功能
flutter 自带的tabbar BottomNavigationBar有长按水波纹效果,不可以添加背景图片功能,如果有这方面的需求,就需要自定义tabbar了 自定义图片 我们使用BottomAp ...
- 小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_2-3.热部署在Eclipse和IDE里面的使用
笔记 3.热部署在Eclipse和IDE里面的使用 简介:讲解热部署的好处及使用注意事项,在eclipse里面默认开启,在IDE里面默认关闭 1.增加依赖 & ...
- 一百一十:CMS系统之剩余菜单栏的页面和视图
增加所有剩余菜单的页面,并用视图渲染,方便后面调试权限控制 {% extends 'cms/cms_base.html' %} {% block title %}板块管理{% endblock %} ...
- c语言数组在作为参数传递时注意事项
1.不能在[]给定大小 2.不要在被调用函数里使用sizeof(a)/sizeof(a[0])形式传递数组大小,直接给出数组长度,或者在 主调函数中使用sizeof(a)/sizeof(a[0])传递 ...
- 给php安装openssl扩展
转自 http://blog.csdn.net/sinat_23678421/article/details/42217971
- node 笔记整理
node 合并多个请求的数据 function getList1(num) { var url= "netease/search?keyword=独孤天下&type=song& ...
- guns系统部署方式及常见问题
项目框架:guns 开发IDE:Idea 2018.1 两种打包方式:war 和jar. 1.正常打包的姿势 1.1按照下图修改为你想到打包的方式. 1.2 执行打包 clean packa ...
- 关于python脚本头部设置#!/usr/bin/python
今天又是贼几把菜的一天0.0 读别人程序的时候看到在python文件头部设置签名,感觉贼几把酷,自己也试着在文件前段设置了一下. 设置还是蛮简单的,设置过程如图所示. 设置后如图所示: 当然你也可能看 ...