题目大意:

  给定一个以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. 在iPad iOS8环境下打开相冊或者拍照

    在iPad下打开相冊或者拍照,假设使用 UIImagePickerController 打开相冊或者拍照,那必需要用到 UIPopoverController 去打开. UIPopoverContro ...

  2. POJ2485 Highways 【MST】

    Highways Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 22842   Accepted: 10525 Descri ...

  3. iOS Code Sign error: Provisioning profile can&#39;t be found 解决方式

    出现error的过程:在执行另外一个xcode项目重置了code sign.回到原来的项目的时候出现这个error 修复方法: targe-build settings-code signing id ...

  4. Activity的launchMode和任务栈小结

    对Activity的launchMode的理解一直没有好好总结下,这两天系统总结下launchMode的使用方法: Activity的launchMode属性决定了Activity和应用程序当前任务栈 ...

  5. SQL Search

    Press TAB to expand wildcard tab键之后,会自动展开,直接枚举表中所有的字段 根据名字查找存储过程,发现找不到 原因是,本地是一个备份库.服务器上通过sql source ...

  6. Android 仿QQ首页的消息和电话的切换,首页的头部(完全用布局控制)

    Android 仿QQ首页的消息和电话的切换,首页的头部(完全用布局控制) 首先贴上七个控制布局代码 1.title_text_sel.xml 字体颜色的切换 放到color文件夹下面 <?xm ...

  7. VMware下最小化安装centos 7 后上网设置

    1.文件/etc/sysconfig/network-scripts/ifcfg-eno16777736 将ONBOOT=no 改为 ONBOOT=yes 保存 2.重启网卡:service netw ...

  8. 《五》uploadify插件上传文件

    下载地址:http://www.uploadify.com/wp-content/uploads/files/uploadify.zip 相关配置:http://www.uploadify.com/d ...

  9. JQ遍历 input 并修改name属性

    1.执行完克隆行后,会出现name属相相同的问题 function addRow(){ var obj = $("tr[name='info']:last"); var objCl ...

  10. QQ互联账号登录

    本文说明的是依据某应用通过网页的qq信息来登录的过程.用途是利用QQ账号就能高速自己主动注冊并可以登录客户应用. 从webserver与腾讯server通信获取开房平台用户OpenID,再在应用ser ...