CF741 D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
题目意思很清楚了吧,那么我们从重排回文串的性质入手。
很容易得出,只要所有字符出现的次数都为偶数,或者有且只有一个字符出现为奇数就满足要求了。
然后想到什么,Hash?大可不必,可以发现字符\(\in [a,v]\),一共\(22\)种,那么我们套路的状压一下即可。
题目放在一棵树上,我们不禁联想树上常用的算法——倍增,树剖,树分治,树上莫队,LCT,但是好像都不好做。
注意到这是一个静态子树信息维护,所以我们可以用一个比较冷门的算法Dsu on Tree(中文名叫树上启发式合并)
它的大体思路很简单,就是对暴力DFS的过程做了优化。先类似于轻重剖分那样求出轻重儿子,然后每次先暴力递归轻儿子,算完贡献然后删去。
然后再统计重儿子的贡献,做完不再删去,然后最后回溯的时候把轻儿子的再加回去。
由于每跳一次重儿子,子树规模至少减少一半,所以每一个节点最多向上合并\(\log n\)次,所以总复杂度是\(O(n\log n)\)的。
再来考虑这个问题,由于异或以及深度的可减性所以我们可以开一个数组统计子树内每种状态的最大深度,每次根据这个数组更新信息即可。
不过要注意这样做的答案是强制过当前根节点的,不过由于这是个最值问题,我们可以把子树的信息向上取\(\max\)。
虽然会有一个\(22\)的常数,但是你要坚信CF神机是可以跑过去的。
总复杂度\(O(22n\log n)\),常数很小。
CODE
#include<cstdio>
#include<cctype>
#define RI register int
#define CI const int&
#define Tp template <typename T>
#define add(x,y) e[++cnt]=(edge){y,head[x]},head[x]=cnt
using namespace std;
const int N=500005,R=22,status=(1<<R)-1,INF=1e9;
struct edge
{
int to,nxt;
}e[N]; int fa[N],n,head[N],cnt,dep[N],prefix[N],son[N],ans[N],size[N],bit[R+5],f[(1<<R)+5]; char ch;
class FileInputOutput
{
private:
static const int S=1<<21;
#define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
#define pc(ch) (Ftop<S?Fout[Ftop++]=ch:(fwrite(Fout,1,S,stdout),Fout[(Ftop=0)++]=ch))
char Fin[S],Fout[S],*A,*B; int Ftop,pt[15];
public:
Tp inline void read(T& x)
{
x=0; char ch; while (!isdigit(ch=tc()));
while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));
}
Tp inline void write(T x)
{
if (!x) return (void)(pc('0'),pc(' ')); RI ptop=0;
while (x) pt[++ptop]=x%10,x/=10; while (ptop) pc(pt[ptop--]+48); pc(' ');
}
inline void get_alpha(char& ch)
{
while (!isalpha(ch=tc()));
}
inline void Fend(void)
{
fwrite(Fout,1,Ftop,stdout);
}
#undef tc
#undef pc
}F;
inline void maxer(int& x,CI y)
{
if (y>x) x=y;
}
#define to e[i].to
inline void DFS1(CI now)
{
size[now]=1; for (RI i=head[now];i;i=e[i].nxt)
{
dep[to]=dep[now]+1; prefix[to]^=prefix[now]; DFS1(to);
size[now]+=size[to]; if (size[to]>size[son[now]]) son[now]=to;
}
}
inline void calc(CI now,CI par)
{
RI i; for (i=0;i<=R;++i) maxer(ans[par],dep[now]+f[prefix[now]^bit[i]]);
for (i=head[now];i;i=e[i].nxt) calc(to,par);
}
inline void Add(CI now)
{
maxer(f[prefix[now]],dep[now]); for (RI i=head[now];i;i=e[i].nxt) Add(to);
}
inline void Del(CI now)
{
f[prefix[now]]=-INF; for (RI i=head[now];i;i=e[i].nxt) Del(to);
}
inline void DFS2(CI now)
{
RI i; for (i=head[now];i;i=e[i].nxt) if (to!=son[now])
DFS2(to),Del(to); if (son[now]) DFS2(son[now]);
maxer(f[prefix[now]],dep[now]); for (i=0;i<=R;++i)
maxer(ans[now],dep[now]+f[prefix[now]^bit[i]]);
for (i=head[now];i;i=e[i].nxt) if (to!=son[now]) calc(to,now),Add(to);
}
#undef to
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
RI i; for (F.read(n),i=2;i<=n;++i) F.read(fa[i]),F.get_alpha(ch),
add(fa[i],i),prefix[i]=1<<ch-'a'; for (i=0;i<=status;++i)
f[i]=-INF; for (i=0;i<R;++i) bit[i]=1<<i;
for (DFS1(1),DFS2(1),i=1;i<=n;++i) ans[i]-=2*dep[i];
for (i=n;i;--i) maxer(ans[fa[i]],ans[i]); for (i=1;i<=n;++i)
F.write(ans[i]); return F.Fend(),0;
}
CF741 D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths的更多相关文章
- CF 741D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths [dsu on tree 类似点分治]
D. Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths CF741D 题意: 一棵有根树,边上有字母a~v,求每个子树中最长的边,满 ...
- Codeforces 741 D - Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
D - Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths 思路: 树上启发式合并 从根节点出发到每个位置的每个字符的奇偶性记为每个位 ...
- CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths 好像这个题只能Dsu On Tree? 有根树点分治 统计子树过x的 ...
- codeforces 741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
题目链接:Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths 第一次写\(dsu\ on\ tree\),来记录一下 \(dsu\ o ...
- codeforces 741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(启发式合并)
codeforces 741D Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths 题意 给出一棵树,每条边上有一个字符,字符集大小只 ...
- CF 741 D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths http://codeforces.com/problemset/probl ...
- 【cf741】D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree)
传送门 题意: 给出一颗以\(1\)为根的有根树,树边带有一个字符(\(a\)~\(v\))的信息. 输出对于每个结点,其子树内最长的简单路径并且满足边上的字符能够组成回文串. 思路: 显然最终的答案 ...
- [Codeforces741D]Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths——dsu on tree
题目链接: Codeforces741D 题目大意:给出一棵树,根为$1$,每条边有一个$a-v$的小写字母,求每个点子树中的一条最长的简单路径使得这条路径上的边上的字母重排后是一个回文串. 显然如果 ...
- Codeforces 741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree)
感觉dsu on tree一定程度上还是与点分类似的.考虑求出跨过每个点的最长满足要求的路径,再对子树内取max即可. 重排后可以变成回文串相当于出现奇数次的字母不超过1个.考虑dsu on tree ...
随机推荐
- 更新 Anaconda 库文件
查看库 Anaconda Navigator中 启动Anaconda Prompt(或Anaconda Navigator中Environment->(base)root->Open te ...
- 【Spring源码解读】bean标签中的属性(二)你可能还不够了解的 abstract 属性和 parent 属性
abstract 属性说明 abstract 在java的语义里是代表抽象的意思,用来说明被修饰的类是抽象类.在Spring中bean标签里的 abstract 的含义其实也差不多,表示当前bean是 ...
- GlusterFS 安装 on centos7
本文演示如何在CentOS7上安装,配置和使用GlusterFS. 1 准备工作 1.1 基础设施 编号 IP OS 主机名 角色 说明 A 192.168.1.101 CentOS7.4 ddc_n ...
- RAS非对称加密与数字证书数字签名
它用图片通俗易懂地解释了,"数字签名"(digital signature)和"数字证书"(digital certificate)到底是什么. 我对这些问题的 ...
- Jenkins版本升级
前言 我们的内网打包环境目前是运行在windows上,采用jenkins.msi 安装成windwos服务的形式. 升级前准备 在jenkins版本升级之后,我使用ThinBackup进行了备份,详细 ...
- Python3 Selenium多窗口切换
Python3 Selenium多窗口切换 以腾讯网(http://www.qq.com/)为例,打开腾讯网,点击新闻,打开腾讯新闻,点击新闻中第一个新闻链接. 在WebDriver中封装了获取当前窗 ...
- JavaScript字符集
引言 JavaScript程序使用Unicode字符集编写.Unicode是ASCII和Latin-1的超集,并支持地球上几乎所有在使用的语言.ECMAScript3要求JavaScript的实现必须 ...
- 转 CSS3+js实现多彩炫酷旋转圆环时钟效果
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...
- 服务创建&删除
创建服务.bat @echo.服务启动...... @echo off @sc create BestoneProductEditSvc binPath= "D:\winSvc\Beston ...
- C#基础知识之泛型集合转换为DataTable
在做项目中,遇到了将集合转换为DataTable的使用,在网上看了资料,在这里记录下来,分享. using System; using System.Collections.Generic; usin ...