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;
}

CF600E Lomsat gelral 和 CF741D Dokhtar-kosh paths的更多相关文章

  1. CF600E Lomsat gelral 【线段树合并】

    题目链接 CF600E 题解 容易想到就是线段树合并,维护每个权值区间出现的最大值以及最大值位置之和即可 对于每个节点合并一下两个子节点的信息 要注意叶子节点信息的合并和非叶节点信息的合并是不一样的 ...

  2. CF600E Lomsat gelral(dsu on tree)

    dsu on tree跟冰茶祭有什么关系啊喂 dsu on tree的模板题 思想与解题过程 类似树链剖分的思路 先统计轻儿子的贡献,再统计重儿子的贡献,得出当前节点的答案后再减去轻儿子对答案的贡献 ...

  3. CF600E:Lomsat gelral(线段树合并)

    Description 一棵树有n个结点,每个结点都是一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号的和. Input 第一行一个$n$.第二行$n$个数字是$c[i]$.后面$n-1$ ...

  4. [CF600E]Lomsat gelral

    题意翻译 一棵树有n个结点,每个结点都是一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号的和. 线段树合并板子题,没啥难度,注意开long long 不过这题$dsu$ $on$ $tre ...

  5. dsu on tree(CF600E Lomsat gelral)

    题意 一棵树有n个结点,每个结点都是一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号的和. dsu on tree 用来解决子树问题 好像不能带修改?? 暴力做这个题,就是每次扫一遍子树统 ...

  6. cf600E. Lomsat gelral(dsu on tree)

    题意 题目链接 给出一个树,求出每个节点的子树中出现次数最多的颜色的编号和 Sol dsu on tree的裸题. 一会儿好好总结总结qwq #include<bits/stdc++.h> ...

  7. CF600E Lomsat gelral——线段树合并/dsu on tree

    题目描述 一棵树有$n$个结点,每个结点都是一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号的和. 这个题意是真的窒息...具体意思是说,每个节点有一个颜色,你要找的是每个子树中颜色的众数 ...

  8. CF600E Lomsat gelral (启发式合并)

    You are given a rooted tree with root in vertex 1. Each vertex is coloured in some colour. Let's cal ...

  9. CF600E Lomsat gelral 树上启发式合并

    题目描述 有一棵 \(n\) 个结点的以 \(1\) 号结点为根的有根树. 每个结点都有一个颜色,颜色是以编号表示的, \(i\) 号结点的颜色编号为 \(c_i\)​. 如果一种颜色在以 \(x\) ...

随机推荐

  1. sorted内置函数

    对List.Dict进行排序,Python提供了两个方法 --------------------------------sorted--------------------------------- ...

  2. 第1/7Beta冲刺

    1.团队成员 成员姓名 成员学号 秦裕航 201731062432(组长) 刘东 201731062227 张旭 201731062129 王伟 201731062214 2.SCRU部分 2.1各成 ...

  3. Mechanical Simulation借助UE发力自动驾驶仿真

    Source https://www.unrealengine.com/en-US/blog/making-autonomous-vehicles-safer-before-they-hit-the- ...

  4. 01 Struts2框架学习(了解一下,已过时)

    1.框架介绍 所谓框架,就是把一些繁琐的重复性代码封装起来,使程序员在编码中把更多的精力放到业务需求的分析和理解上面. 特点:封装了很多细节,程序员在使用的时候会非常简单. 早前,有三大框架strut ...

  5. AS3中 is,as,typeof的区别

    AS3中 is,as,typeof的区别 . var my_num:Number=9;trace(typeof my_num);var my_object:Array=["语文", ...

  6. 网页中插入Flash动画(.swf)代码和常用参数设置

    我们现在大部分人做网页,都是直接用DW插入flash,而且DW也是所见即所得,直接生成了相应的flash显示代码.可是我们又有多少人了解这些直接由DW生成的代码呢?其实我接触flash player标 ...

  7. GOF 的23种JAVA常用设计模式 学习笔记 持续更新中。。。。

    前言: 设计模式,前人总结下留给后人更好的设计程序,为我们的程序代码提供一种思想与认知,如何去更好的写出优雅的代码,23种设计模式,是时候需要掌握它了. 1.工厂模式 大白话:比如你需要一辆汽车,你无 ...

  8. JavaJDK多任务执行框架(六)

    class Temp extends Thread { public void run() { System.out.println("run"); } } public clas ...

  9. 2.3_Database Interface ODBC组成原理

    从某种意义上来讲,ODBC实际上主要是一个数据库的访问库(API),它包含访问不同数据库所要求的ODBC驱动程序.应用程序要操作不同类型的数据库,只要调用ODBC所支持的函数,动态链接到不同的驱动程序 ...

  10. java框架学习系列

    这篇文章的目的主要是作为一个框架学习的索引,方便查找及顺序学习 一.struts2学习 1. java之struts框架入门教程 2. java之struts2的执行流程讲解 3. java之stru ...