CF600E Lomsat gelral 和 CF741D Dokhtar-kosh paths
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的更多相关文章
- CF600E Lomsat gelral 【线段树合并】
题目链接 CF600E 题解 容易想到就是线段树合并,维护每个权值区间出现的最大值以及最大值位置之和即可 对于每个节点合并一下两个子节点的信息 要注意叶子节点信息的合并和非叶节点信息的合并是不一样的 ...
- CF600E Lomsat gelral(dsu on tree)
dsu on tree跟冰茶祭有什么关系啊喂 dsu on tree的模板题 思想与解题过程 类似树链剖分的思路 先统计轻儿子的贡献,再统计重儿子的贡献,得出当前节点的答案后再减去轻儿子对答案的贡献 ...
- CF600E:Lomsat gelral(线段树合并)
Description 一棵树有n个结点,每个结点都是一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号的和. Input 第一行一个$n$.第二行$n$个数字是$c[i]$.后面$n-1$ ...
- [CF600E]Lomsat gelral
题意翻译 一棵树有n个结点,每个结点都是一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号的和. 线段树合并板子题,没啥难度,注意开long long 不过这题$dsu$ $on$ $tre ...
- dsu on tree(CF600E Lomsat gelral)
题意 一棵树有n个结点,每个结点都是一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号的和. dsu on tree 用来解决子树问题 好像不能带修改?? 暴力做这个题,就是每次扫一遍子树统 ...
- cf600E. Lomsat gelral(dsu on tree)
题意 题目链接 给出一个树,求出每个节点的子树中出现次数最多的颜色的编号和 Sol dsu on tree的裸题. 一会儿好好总结总结qwq #include<bits/stdc++.h> ...
- CF600E Lomsat gelral——线段树合并/dsu on tree
题目描述 一棵树有$n$个结点,每个结点都是一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号的和. 这个题意是真的窒息...具体意思是说,每个节点有一个颜色,你要找的是每个子树中颜色的众数 ...
- CF600E Lomsat gelral (启发式合并)
You are given a rooted tree with root in vertex 1. Each vertex is coloured in some colour. Let's cal ...
- CF600E Lomsat gelral 树上启发式合并
题目描述 有一棵 \(n\) 个结点的以 \(1\) 号结点为根的有根树. 每个结点都有一个颜色,颜色是以编号表示的, \(i\) 号结点的颜色编号为 \(c_i\). 如果一种颜色在以 \(x\) ...
随机推荐
- python爬虫1
1 网页结构 html:超文本标记语言------->类似人的鼻子耳朵,长在那里,大体骨架就是那个样子 css:层叠样式表------->这个是外观的深化,比如贴个双眼皮,橙色眼睛... ...
- Android Capabilities讲解
1.Capabilities介绍 可以看下之前代码里面设置的capabilities DesiredCapabilities capabilities =newDesiredCapabilities( ...
- 在ensp上的进行的浮动路由
原理 实验模拟内容 搭建实验拓扑 相关参数 其他设置端口ip都一样,serial也一样(三个路由器都要设置的) 简单测试一下连通性 下面我们分别在路由器上配置所在网段的静态路由 配置完之后我们来查看一 ...
- mysql在windows下的服务安装
前提必须用管理员身份运行 1.删除Mysql服务,打开命令行,输入下面的指令 sc delete MySql 2.初始化一下数据,比如配置文件中设置了数据的存储路径,日志位置等:该命令必须用管理员身份 ...
- tetetet
http://www.wuwenhui.cn/2623.html http://www.360doc.com/content/16/1104/09/36005694_603810507.shtml
- Java基础之(四)HashMap(jdk10)
JDK1.7以前的HashMap jdk1.7中,当冲突时,在冲突的地址上生成一个链表,将冲突的元素的key,通过equals进行比较,相同即覆盖,不同则添加到链表上,此时如果链表过长,效率就会大大降 ...
- 手撕面试官系列(二):开源框架面试题Spring+SpringMVC+MyBatis
文章首发于今日头条:https://www.toutiao.com/i6712324863006081549/ 前言 跳槽时时刻刻都在发生,但是我建议大家跳槽之前,先想清楚为什么要跳槽.切不可跟风,看 ...
- C++—多态与继承
一.基本概念 1.类的继承,是新的类从已有类那里得到已有的特性.或从已有类产生新类的过程就是类的派生.原有的类称为基类或父类,产生的新类称为派生类或子类. 2.派生类的声明: class 派生类名:继 ...
- 电路板工艺中的NPTH和PTH
今天收到PCB生产公司发来的工程咨询单 Q1:请问贵司资料中的沉头孔是做PTH沉头还是做NPTH沉头? 好吧,鄙人见识少,第一次听说PTH和NPTH,查资料吧,一张图看一下就明白了. 另一种比较小的P ...
- 数据结构与算法(Python)
数据结构与算法(Python) Why? 我们举一个可能不太恰当的例子: 如果将最终写好运行的程序比作战场,我们码农便是指挥作战的将军,而我们所写的代码便是士兵和武器. 那么数据结构和算法是什么?答曰 ...