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 ...
随机推荐
- Android 滑动定位+吸附悬停效果实现
在前两篇文章中,分别介绍了tablayout+scrollview 和 tablayout+recyclerview 实现的滑动定位的功能,文章链接: Android 实现锚点定位 Android t ...
- web自动化 基于python+Selenium+PHP+Ftp实现的轻量级web自动化测试框架
基于python+Selenium+PHP+Ftp实现的轻量级web自动化测试框架 by:授客 QQ:1033553122 博客:http://blog.sina.com.cn/ishou ...
- css文本超出隐藏显示省略号
p style="width: 300px;overflow: hidden;white-space: nowrap;text-overflow: ellipsis;"> 如 ...
- MFC更换画笔(画刷)颜色以及画眼睛(GDI画图)
MFC画眼睛 换画笔(画刷)颜色(参考链接:https://blog.csdn.net/sunxiving/article/details/51272001) 由于画笔一旦创建后就无法修改.所以要修改 ...
- spring学习总结——介绍
介绍:以下博客的内容都是依据<spring实战4>这本书.spring4.0 来总结. 一.spring作用 Spring可以做很多事情,它为企业级开发提供给了丰富的功能,但是这些功能的底 ...
- coTurn 运行在Windows平台的方法及服务与客户端运行交互流程和原理
coTurn是一个开源的STUN和TURN及ICE服务项目,只是不支持Windows.为了在window平台上使用coTurn源码,需要在windows平台下安装Cygwin环境,并编译coTurn源 ...
- backup是个相对论
工作互备,是很多团队领导者都关注的事情.显然,当一项任务由两个(甚至两个以上的人)来完成,当任务交付使用后出现问题时,不会因为其中某一个成员的缺席而导致问题一时处理不了.如果某个任务只是由一个人来担当 ...
- Response()的对象
addCookie(Cookie cookie):这个方法是向Response容器中添加一个Cookie,然后服务器容器会自动的将这个Cookie回写给客户机的,至于Cookie的相关知识我们会在后面 ...
- 自动化测试基础篇--Selenium中数据参数化之TXT
摘自https://www.cnblogs.com/sanzangTst/p/7722594.html 一.搜索参数化 在TXT文件中保存需要搜索的内容: 测试代码: 1 #!/usr/bin/env ...
- CentOS 7.0下安装Python3.6
CentOS 7.0自带Python2.7 安装Python3.6步骤 1.安装依赖 yum install -y zlib-devel bzip2-devel openssl-devel ncurs ...