题目大意:

  给定一个以1为根的树,每条路径上都有一个字符(a~v共22个)询问对于每一个子树内最长的路径上字母经排序后可以形成回文串的最长路径多长

解题思路:

  假定给你一个字符串,如何判定其经打乱能否形成回文串,那就是说所有字符中最多只有一个能出现奇数次,22个字符,可以用2进制表示每个字符出现的次数奇偶性,1为奇0为偶,那么处理出一个点到根节点路径上的异或和(设为xi),如果两个节点i,j的xi=xj那么就说明这两个点的路径上符合要求。

  暴力的思路:暴力搜索一棵树中所有的xi看看有没有相同或差一位的再进行答案更新。

  考虑优化,既然是不同子树中的点,那么就可以用一个数组存起来异或和为x的最大深度maxdeep[x],每次进去找,找完再把整颗子树推进去。这样就是O(n2)

  这样就可以用DSU了,每次处理子树时,最后处理重儿子,非重儿子直接推倒,在更新上层时直接在重儿子版本上构建数组,再重建轻儿子,注意更新答案时要更新为子树最大值,跨字数最大值,返祖链最大值中的最大值。时间复杂度O(nlogn)

  DSU还是十分优秀啊

  代码:

 #include<cstdio>
#include<cstring>
#include<algorithm>
struct pnt{
int hd;
int dp;
int wgt;
int mxs;
int ans;
int xr;
}p[];
struct ent{
int twd;
int lst;
int vls;
}e[];
int n;
int cnt;
char cmd[];
int mxdp[];
void ade(int f,int t,int v)
{
cnt++;
e[cnt].twd=t;
e[cnt].lst=p[f].hd;
e[cnt].vls=v;
p[f].hd=cnt;
}
void Basic_dfs(int x,int f)
{
p[x].dp=p[f].dp+;
p[x].wgt=;
int maxs=-;
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
p[to].xr=p[x].xr^e[i].vls;
Basic_dfs(to,x);
p[x].wgt+=p[to].wgt;
if(maxs<p[to].wgt)
{
maxs=p[to].wgt;
p[x].mxs=to;
}
}
}
void Build_dfs(int x)
{
mxdp[p[x].xr]=std::max(mxdp[p[x].xr],p[x].dp);
for(int i=p[x].hd;i;i=e[i].lst)
Build_dfs(e[i].twd);
}
void Destory_dfs(int x)
{
mxdp[p[x].xr]=;
for(int i=p[x].hd;i;i=e[i].lst)
Destory_dfs(e[i].twd);
}
void Ans_dfs(int x,int a)
{
if(mxdp[p[x].xr])
p[a].ans=std::max(p[a].ans,p[x].dp+mxdp[p[x].xr]-*p[a].dp);
for(int i=;i<;i++)
{
int tmp=<<i;
if(mxdp[p[x].xr^tmp])
p[a].ans=std::max(p[a].ans,p[x].dp+mxdp[p[x].xr^tmp]-*p[a].dp);
}
for(int i=p[x].hd;i;i=e[i].lst)
Ans_dfs(e[i].twd,a);
}
void DSU_dfs(int x,bool hvs)
{
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(to==p[x].mxs)
continue;
DSU_dfs(to,false);
p[x].ans=std::max(p[x].ans,p[to].ans);
}
if(p[x].mxs)
{
DSU_dfs(p[x].mxs,true);
p[x].ans=std::max(p[x].ans,p[p[x].mxs].ans);
}
if(mxdp[p[x].xr])
p[x].ans=std::max(p[x].ans,mxdp[p[x].xr]-p[x].dp);
for(int i=;i<;i++)
{
int tmp=<<i;
if(mxdp[p[x].xr^tmp])
p[x].ans=std::max(p[x].ans,mxdp[p[x].xr^tmp]-p[x].dp);
}
mxdp[p[x].xr]=std::max(p[x].dp,mxdp[p[x].xr]);
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(to==p[x].mxs)
continue;
Ans_dfs(to,x);
Build_dfs(to);
}
if(hvs)
return ;
Destory_dfs(x);
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
{
int x;
scanf("%d",&x);
scanf("%s",cmd);
int tmp=<<(cmd[]-'a');
ade(x,i,tmp);
}
Basic_dfs(,);
DSU_dfs(,true);
for(int i=;i<=n;i++)
printf("%d ",p[i].ans);
puts("");
return ;
}

CF741DArpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(DSU on tree)的更多相关文章

  1. Codeforces 741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree)

    感觉dsu on tree一定程度上还是与点分类似的.考虑求出跨过每个点的最长满足要求的路径,再对子树内取max即可. 重排后可以变成回文串相当于出现奇数次的字母不超过1个.考虑dsu on tree ...

  2. 【CodeForces】741 D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree)

    [题意]给定n个点的树,每条边有一个小写字母a~v,求每棵子树内的最长回文路径,回文路径定义为路径上所有字母存在一种排列为回文串.n<=5*10^5. [算法]dsu on tree [题解]这 ...

  3. CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree)

    一棵根为1 的树,每条边上有一个字符(a-v共22种). 一条简单路径被称为Dokhtar-kosh当且仅当路径上的字符经过重新排序后可以变成一个回文串. 求每个子树中最长的Dokhtar-kosh路 ...

  4. 【cf741】D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree)

    传送门 题意: 给出一颗以\(1\)为根的有根树,树边带有一个字符(\(a\)~\(v\))的信息. 输出对于每个结点,其子树内最长的简单路径并且满足边上的字符能够组成回文串. 思路: 显然最终的答案 ...

  5. 【CF741D】Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree)

    题意:我们称一个字符串为周驿东串当且仅当重排它的字符可以组成一个回文串. 给出一个n个点的有根树,根为1,每条边上有一个从a到v的字符,求每个点的子树中所有简单路径可以组成的周驿东串中的最长长度. n ...

  6. 【CF600E】Lomsat gelral(dsu on tree)

    [CF600E]Lomsat gelral(dsu on tree) 题面 洛谷 CF题面自己去找找吧. 题解 \(dsu\ on\ tree\)板子题 其实就是做子树询问的一个较快的方法. 对于子树 ...

  7. 【Luogu U41492】树上数颜色——树上启发式合并(dsu on tree)

    (这题在洛谷主站居然搜不到--还是在百度上偶然看到的) 题目描述 给一棵根为1的树,每次询问子树颜色种类数 输入输出格式 输入格式: 第一行一个整数n,表示树的结点数 接下来n-1行,每行一条边 接下 ...

  8. CF375D Tree and Queries(dsu on tree)

    思路 dsu on tree的板子,可惜人傻把 for(int i=fir[u];i;i=nxt[i]) 打成 for(int i=fir[u];i<=n;i++) 调了两个小时 这题要求维护& ...

  9. CF600E Lomsat gelral(dsu on tree)

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

随机推荐

  1. php实现模拟登陆

    在不考虑验证码的情况一下,php实现模拟登陆,网上给的办法通常是採用curl来模拟实现,可是curl实现的是server端与server端建立了会话,仅仅能模拟登陆之后获取登陆之后的数据.无法将coo ...

  2. windows下用ADT进行android NDK开发的具体教程(从环境搭建、配置到编译全过程)

    郑重申明:如需转载本博客,请注明出处,谢谢! 这几天在学习android NDK的开发.那么首先让我们来看看android NDK开发的本质是什么. NDK(Native Development Ki ...

  3. LINQ查询基础

    一.什么是LINQ LINQ是Language Integrate Query的缩写,意为语言集成查询,是微软在.Net Framework 4.5版中推出的主要特性之一. 它为开发人员提供了统一的数 ...

  4. apidoc接口文档的快速生成

    官方文档连接:http://apidocjs.com/#demo apidoc是一个轻量级的在线REST接口文档生成系统,支持多种主流语言,包括Java.C.C#.PHP和Javascript等.使用 ...

  5. oracle中查询表的信息,包括表名,字段名,字段类型,主键,外键唯一性约束信息

    来源于网上整理 总结了一下oracle中查询表的信息,包括表名,字段名,字段类型,主键,外键唯一性约束信息,索引信息查询SQL如下,希望对大家有所帮助: 1.查询出所有的用户表select * fro ...

  6. PHP定时执行任务

    ignore_user_abort();//关掉浏览器,PHP脚本也可以继续执行. set_time_limit(0);// 通过set_time_limit(0)可以让程序无限制的执行下去 $int ...

  7. PHP设置30秒内对页面的访问次数

    <?php //Calculate 60 days in the future //seconds * minutes * hours * days + current time $intime ...

  8. CentOs虚拟机能够互相ping通,但无法訪问虚拟机服务

    CentOs虚拟机能够互相ping通,但无法訪问虚拟机服务 虚拟机ip:192.168.0.57 主机 ip:192.168.0.80 在虚拟机上搭建了php环境.虚拟机CentOs,主机win7 虚 ...

  9. Struts(18)标签

    控件标签 Struts 2 的标签有一组标签.更easy控制流程页面运行.下面是重要的Struts2控制标签列表: if /else 标签: 这些标签运行可在每一种语言找到的一种基本条件流程. 'If ...

  10. 小白学开发(iOS)OC_ SEL数据类型(2015-08-10)

    // //  main.m //  SEL数据类型 // //  Created by admin on 15/8/12. //  Copyright (c) 2015年 admin. All rig ...