题目链接

题目:

给定一棵nnn个结点的树,每个点有一个权值aia_iai​,问有多少个点uuu满足从uuu出发到其他所有点的路径中都不存在两个权值相同的点。
(1≤n≤2×105,1≤ai≤109)(1 \le n \le 2 \times10^5,1 \le a_i \le 10^9)(1≤n≤2×105,1≤ai​≤109)

题解:

一开始拿到这个题我想的是用换根dpdpdp,但发现有一些信息维护不了。
这道题应该从性质入手,先随便确定一个根,考虑有两个权值相同的点的情况,设为u,vu,vu,v:
(1)u,vu,vu,v存在祖先关系
   不妨设uuu是vvv的祖先,那么显然可能满足题意的点只能是在vvv所在的那棵以uuu的某个子节点为根的子树中的而又不在以vvv为根的子树中的点。觉得不清楚可以看图:

(2)u,vu,vu,v不存在祖先关系
   那么可以确定在以uuu为根的子树中和以vvv为根节点的子树中的点是不满足题意的。
那么上述的判法将所有不满足题意的点都判掉了吗?答案是肯定的,因为如果一个点不满足题意,那么这个点到其他所有结点的路径中一定会出现至少两者之一的情况,所以所有不合法的点都会被判掉。
正确性得到证明以后,来考虑具体的算法实现。我们可以用打01标记的方式来维护点的合法性,由于有多次更新操作和单次查询操作,所以可以用树上差分来维护。我们用fu=0/1f_u=0/1fu​=0/1来标识点的合法状态,对于情况(1),我们在遍历uuu的所有子节点,如果在以vvv为根的子树中存在和aua_uau​权值相同的点,那么令froot++,fv−−f_{root}++,f_v--froot​++,fv​−−,这里具体来讲可以维护一个全局的mapmapmap变量numnumnum,存下当前dfsdfsdfs到的点的权值出现情况,在dfsdfsdfs进入vvv子树前存下当前的numaunum_{a_u}numau​​,从vvv子树出来的时候比较当前的numaunum_{a_u}numau​​和之前存下的是否相等,如果不相等,说明以aua_uau​为权值的点在vvv子树中出现了;对于情况(2),也是用一样的思路去维护,如果在以uuu为根节点的子树中没有出现的以aua_uau​为权值的点,那么就出现了情况(2),这时将fu++f_u++fu​++即可。最后dfsdfsdfs一遍下顺标记。fff值为0的点就是满足题意的点。

复杂度:O(nlogn)O(nlogn)O(nlogn)

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#include<bitset>
#include<sstream>
#include<ctime>
//#include<chrono>
//#include<random>
//#include<unordered_map>
using namespace std;#define ll long long
#define ls o<<1
#define rs o<<1|1
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define sz(x) (int)(x).size()
#define all(x) (x).begin(),(x).end()
const double pi=acos(-1.0);
const double eps=1e-6;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const int maxn=2e5+5;
ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;
}
int n,ans;
vector<int>g[maxn];
int f[maxn],a[maxn];
map<int,int>num,sta;
void dfs(int u,int fa){int base=sta[a[u]];sta[a[u]]++;for(auto v:g[u]){if(v==fa)continue;int tmp=sta[a[u]];dfs(v,u);if(tmp!=sta[a[u]]){f[1]++;f[v]--;}}int diff=sta[a[u]]-base;if(diff!=num[a[u]]){f[u]++;}
}
void solve(int u,int fa,int x){if(!x){++ans;}for(auto v:g[u]){if(v==fa)continue;solve(v,u,x+f[v]);}
}
int main(void){// freopen("in.txt","r",stdin);scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d",&a[i]);num[a[i]]++;}int u,v;for(int i=1;i<=n-1;i++){scanf("%d%d",&u,&v);g[u].pb(v);g[v].pb(u);}dfs(1,0);ans=0;solve(1,0,f[1]);printf("%d\n",ans);return 0;
}

codeforces1467E Distinctive Roots in a Tree相关推荐

  1. codeforces1467 E. Distinctive Roots in a Tree(树上差分)

    E. Distinctive Roots in a Tree 树上差分 如果当前节点u的某一棵子树中的某个节点的值和当前节点相同,那么除了当前节点这一棵子树节点,其他节点(其他子树以及u上面的节点)一 ...

  2. Codeforces Round #695(Div. 2)

    Codeforces Round #695 (Div. 2) 1467A Wizard of Orz 1467B Hills And Valleys 1467C Three Bags 1467D Su ...

  3. Paper翻译:《A Novel Convolutional Neural Network Based Model for Recognition and Classification of App》

    论文名称:<A Novel Convolutional Neural Network Based Model for Recognition and Classification of Appl ...

  4. LintCode2016年8月8日算法比赛----子树

    子树 题目描述 有两个不同大小的二叉树:T1有上百万的节点:T2有好几百的节点.请设计一种算法,判定T2是否为T1的子树. 注意事项若 T1 中存在从节点 n 开始的子树与 T2 相同,我们称 T2 ...

  5. 人工智能研究的内容:_更深入:人工智能研究的思想史

    人工智能研究的内容: by Elena Nisioti 由Elena Nisioti 更深入:人工智能研究的思想史 (Going deeper: A history of ideas in AI re ...

  6. Instruments详解

    使用Instruments可以监测分析app内存相关的 Overall Memory Use. Leaked Memory. Abandoned Memory. Zombies等内容. 1.Blank ...

  7. Polygon zkEVM——Hermez 2.0简介

    1. 引言 前序博客有: ZK-Rollups工作原理 近期,Polygon团队开源了其Hermez 2.0 zkEVM代码,公开测试网即将上线: https://github.com/0xpolyg ...

  8. 树形结构数据封装(及拉平)的几种方法

    java(for循环处理.递归处理.map处理) public class DemoApplicationTests {/*for循环写法*//*** @param args*/public stat ...

  9. EasyUI:combotree(树形下拉框)复选框选中父节点(子节点的状态也全部选中)输入框中只显示父节点的文本值

    在开发过程中遇到的小案例 效果展示 未处理之前的效果: 处理之后的效果: 需求详情 combotree(树形下拉框)复选框选中父节点时输入框只显示父节点的文本值,但是子节点的状态是选中的. 当所有子节 ...

  10. 数据结构二叉排序树建立_数据结构101什么是二叉搜索树

    数据结构二叉排序树建立 In everyday life, we need to find things or make decisions, and one way to make that pro ...

最新文章

  1. 故对于回调函数来说,在其内部使用 this 是不把稳的做法,解决方案可以在其调用时使用 call / apply / bind 显示绑定。
  2. 使用RecycleView实现无限滚动的日历
  3. 一个用Shell脚本写的猜丁壳游戏
  4. 基类数组存放派生类_永远不要将派生类数组赋值给基类类型指针
  5. linux 以某个用户执行,Linux root用户肿么以制定的用户去执行某个程序。
  6. 再问数据中台-数据中台和数据仓库,数据平台的关系是什么?
  7. 照片快照清除 android,如何在Android中删除和恢复照片
  8. mac配置php mysql_mac配置Apache+php+mysql
  9. 8年软件测试工程师感悟:与薪资相匹配的永远是实力
  10. 系统调用之creat
  11. Raki的读paper小记:FastText:Enriching Word Vectors with Subword Information
  12. 回到顶部的几种实现方法
  13. Paragon NTFS 15Mac上NTFS分区的必备工具
  14. 计算机控制实验报告组态软件学习,中北大学组态软件实验报告
  15. 微服务下蓝绿部署、红黑部署、AB测试、灰度发布、金丝雀发布、滚动发布的概念与区别...
  16. python中用pip安装出现Microsoft Visual C++ 14.0 is required. Get it with Microsoft Visual C++ Build Tools
  17. Win10右键文件夹卡死如何处理
  18. 《ChatGPT》自动写代码、写作文,使用教程来了
  19. 5G基站辐射致癌?一个源自19年前的某权威报告引发的谣言
  20. Js 怎么遍历json对象所有key及根据动态key获取值

热门文章

  1. 3dmax2014 uv用法_3dmax2014UVW是什么意思,怎么展开UVWID:30075914
  2. 创建CHM格式电子书
  3. 解决出租屋网络故障的步骤及最佳组网方案
  4. linux redis 调优,关于redis状态监控和性能调优详解
  5. C. Remove Adjacent
  6. 老罗的悔改与锤子的落俗
  7. teeth mirror牙小护牙膏让你唇红齿白,亮白笑容不是梦
  8. 管理类联考-英语: 前导( 三 )
  9. 哈哈,用FlexGrid做开发,轻松处理百万级表格数据
  10. 服务器带宽打开网页很慢,移动宽带打开网页慢?两招治本移动宽带打开网页速度慢的解决方法...