Lomsat gelral

一棵以\(1\)为根的树有\(n\)个结点,每个结点都有一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号(若有数量一样的,则求编号和)。

\(n \le 10^5\)

题解

dsu on tree模板题。

暴力做法其实很简单,就是枚举这个点,然后扫一遍子树得到答案,然后清空cnt数组。

我们会发现它做了一些无用功,比如说最后一次清空,其实可以用于他的父节点,这样父节点就可以少算一个子节点。

我们想让尽量大的子树不擦除,那么就树剖剖出重儿子,重儿子不擦除就可以了。

这样一个点会被祖先统计到当且仅当它在轻儿子子树中,所以一个点被统计不超过\(O(\log n)\)次。总时间复杂度\(O(n\log n)\)。

#include<bits/stdc++.h>
#define co const
#define il inline
template<class T> T read(){
T x=0,w=1;char c=getchar();
for(;!isdigit(c);c=getchar())if(c=='-') w=-w;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*w;
}
template<class T>il T read(T&x){
return x=read<T>();
}
using namespace std;
typedef long long LL; co int N=100001;
int n,val[N];
vector<int> e[N]; int fa[N],siz[N],son[N]; void dfs1(int x,int fa){
siz[x]=1;
for(unsigned i=0;i<e[x].size();++i){
int y=e[x][i];
if(y==fa) continue;
::fa[y]=x;
dfs1(y,x);
siz[x]+=siz[y];
if(siz[y]>siz[son[x]]) son[x]=y;
}
} LL ans[N];
int cnt[N],vis[N];
int maxc;LL sum; void change(int x,int d){
cnt[val[x]]+=d;
if(d>0&&cnt[val[x]]>=maxc){
if(cnt[val[x]]>maxc) sum=0,maxc=cnt[val[x]];
sum+=val[x];
}
for(unsigned i=0;i<e[x].size();++i){
int y=e[x][i];
if(y==fa[x]||vis[y]) continue;
change(y,d);
}
}
void dfs2(int x,int use){
for(unsigned i=0;i<e[x].size();++i){
int y=e[x][i];
if(y==fa[x]||y==son[x]) continue;
dfs2(y,0);
}
if(son[x]) dfs2(son[x],1),vis[son[x]]=1;
change(x,1),ans[x]=sum;
if(son[x]) vis[son[x]]=0;
if(!use) change(x,-1),maxc=sum=0;
} int main(){
read(n);
for(int i=1;i<=n;++i) read(val[i]);
for(int i=1,x,y;i<n;++i){
read(x),read(y);
e[x].push_back(y),e[y].push_back(x);
}
dfs1(1,0);
dfs2(1,0);
for(int i=1;i<=n;++i) printf("%lld ",ans[i]);
return 0;
}

Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

一棵以\(1\)号点为根的树,每条边上有一个小写字母\(a\sim v\)。定义一条路经是好的,当且仅当这条路径上经过的所有小写字母重排后可以构成回文串。

求以每个点为根的子树中最长的好的路径。

\(n \le 10^5\)

题解

如果重排后能形成回文串,那么出现奇数次的字符最多有1个。

首先,对于一条字母是\(c\)的边,定义其权值为\(2^c\)。

这样一条路经是好的就当且仅当这条路径的异或和二进制位中的\(1\)的个数不超过\(1\)。

在处理以某一点为根的子树时,开桶,记\(f[i]\)表示到根路径异或和为\(i\)的点的最大深度,可以类似点分的方法计算答案并更新桶。

然后套个dsu on tree,这道题就解决了。时间复杂度\(O(n \log n)\)。

#include<bits/stdc++.h>
#define co const
#define il inline
template<class T> T read(){
T x=0,w=1;char c=getchar();
for(;!isdigit(c);c=getchar())if(c=='-') w=-w;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*w;
}
template<class T>il T read(T&x){
return x=read<T>();
}
using namespace std; co int N=500000+5;
int n,nx[N],to[N],val[N];
int siz[N],son[N],dep[N];
int pos[N],dfn,id[N],lst[N]; void dfs1(int x){
siz[x]=1,id[pos[x]=++dfn]=x;
for(int y=to[x];y;y=nx[y]){
dep[y]=dep[x]+1,val[y]=val[y]^val[x];
dfs1(y);
siz[x]+=siz[y];
if(siz[y]>siz[son[x]]) son[x]=y;
}
lst[x]=dfn;
} int f[1<<22],ans[N]; void dfs2(int x,int use){
for(int y=to[x];y;y=nx[y])
if(y!=son[x]) dfs2(y,0),ans[x]=max(ans[x],ans[y]);
if(son[x]) dfs2(son[x],1),ans[x]=max(ans[x],ans[son[x]]);
// cerr<<x<<" ans="<<ans[x]<<endl;
if(f[val[x]]) ans[x]=max(ans[x],f[val[x]]-dep[x]);
for(int i=0;i<22;++i)if(f[val[x]^(1<<i)])
ans[x]=max(ans[x],f[val[x]^(1<<i)]-dep[x]);
f[val[x]]=max(f[val[x]],dep[x]);
// cerr<<x<<" ans="<<ans[x]<<endl;
for(int y=to[x];y;y=nx[y])if(y!=son[x]){
for(int i=pos[y];i<=lst[y];++i){
int z=id[i];
if(f[val[z]]) ans[x]=max(ans[x],f[val[z]]+dep[z]-(dep[x]<<1));
for(int j=0;j<22;++j)if(f[val[z]^(1<<j)])
ans[x]=max(ans[x],f[val[z]^(1<<j)]+dep[z]-(dep[x]<<1));
}
for(int i=pos[y];i<=lst[y];++i){
int z=id[i];
f[val[z]]=max(f[val[z]],dep[z]);
}
}
// cerr<<x<<" ans="<<ans[x]<<endl;
if(!use) for(int i=pos[x];i<=lst[x];++i) f[val[id[i]]]=0;
} int main(){
read(n);
for(int i=2;i<=n;++i){
int fa=read<int>();char ch=getchar();
nx[i]=to[fa],to[fa]=i,val[i]=1<<(ch-'a');
}
dfs1(1);
dfs2(1,0);
for(int i=1;i<=n;++i) printf("%d ",ans[i]);
return 0;
}

最新文章

  1. RPM方式安装MySQL5.6
  2. checkbox标签已有checked=checked属性但是不显示勾选
  3. JavaWeb学习--Servlet认识
  4. 理解KMP算法
  5. iOS中dyld缓存的实现原理是怎样的?
  6. Objective-C 高性能的循环遍历 forin - NSEnumerator - 枚举 优化
  7. linux c编程 多线程(初级)《转载》---赠人玫瑰,手有余香!
  8. Thread 方法
  9. wordpress主题
  10. DCOS实践分享(5):Open DCOS深入分析
  11. js学习2
  12. .net core 2.2 修改IdentityUser主键标识类型
  13. 被顶级学术期刊枪毙的p.Value到底是个什么鬼
  14. 自学python 4.
  15. excel 八位二进制转换为十六进制公式
  16. API网关设计(一)之Token多平台身份认证方案(转载)
  17. Flutter - TabBar导航栏切换后,状态丢失
  18. VS2010/MFC编程入门之三十八(状态栏的使用详解)
  19. 如何利用Visio设计一个系统的结构图
  20. 打包应用和构建Docker镜像(docker在windows上)

热门文章

  1. jQuery实现简单导航栏的样式切换
  2. Asp.net Core CORS 跨域
  3. day45——html常用标签、head内常用标签
  4. C++多态性----运算符重载与虚函数
  5. Python Web开发技术栈
  6. Pycharm下直接升级库所遇到的&#39;main&#39;问题
  7. 全栈项目|小书架|服务器开发-NodeJS 使用 JWT 实现登录认证
  8. python 包 安装 加速 pip anaconda
  9. cefsharp System.IO.FileNotFoundException: 未能加载文件或程序集“CefSharp.Core.dll”或它的某一个依赖项。
  10. 1.1 文档PUT内部原理