D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

http://codeforces.com/problemset/problem/741/D

题意:

  一棵根为1 的树,每条边上有一个字符(a-v共22种)。 求每个子树内的最长的路径,使得路径上的边按照一定顺序排列后是回文串。

分析:

  dsu on tree。询问子树信息。

  首先将这22个字符,转化为二进制。a=1,b=10,c=100...如果一条路径可以是回文串,那么要求路径的异或和最多有一个1。所以记录下从根到每个点的异或和,那么一条路径的异或和就是dis[u]^dis[v],lca上面的异或后消失了。

  之后维护每个子树内异或和为x的最大深度是多少。记为f。

  更新答案:按照点分治的思想,先更新不经过根的,然后求出经过根的(更新分成两步,第一步更新答案,第二步更新f数组。防止更新了在子树内部的)。

代码:

 #include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#include<cctype>
#include<set>
#include<vector>
#include<queue>
#include<map>
using namespace std;
typedef long long LL; inline int read() {
int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} const int N = ; int head[N], nxt[N], to[N], len[N], En;
int fa[N], siz[N], son[N], dis[N], deth[N], ans[N];
int f[( << ) + ];
int Mx, D; void add_edge(int u,int v,int w) {
++En; to[En] = v; len[En] = w; nxt[En] = head[u]; head[u] = En;
} void dfs(int u) {
siz[u] = ;
deth[u] = deth[fa[u]] + ;
for (int i=head[u]; i; i=nxt[i]) {
int v = to[i];
fa[v] = u;
dis[v] = dis[u] ^ ( << len[i]);
dfs(v);
siz[u] += siz[v];
if (!son[u] || siz[son[u]] < siz[v]) son[u] = v;
}
} void add(int u) {
if (f[dis[u]]) Mx = max(Mx, deth[u] + f[dis[u]] - D); // 异或后为0
for (int i=; i<; ++i) // 异或后有一个1
if (f[( << i) ^ dis[u]]) Mx = max(Mx, deth[u] + f[( << i) ^ dis[u]] - D);
}
void Calc(int u) { // 计算答案
add(u);
for (int i=head[u]; i; i=nxt[i]) Calc(to[i]);
}
void upd(int u) {
f[dis[u]] = max(deth[u], f[dis[u]]);
}
void update(int u) { // 更新f数组
upd(u);
for (int i=head[u]; i; i=nxt[i]) update(to[i]);
}
void Clear(int u) {
f[dis[u]] = ;
for (int i=head[u]; i; i=nxt[i]) Clear(to[i]);
} void solve(int u,bool c) {
for (int i=head[u]; i; i=nxt[i])
if (to[i] != son[u]) solve(to[i], );
if (son[u]) solve(son[u], ); D = deth[u] * ;
for (int i=head[u]; i; i=nxt[i]) Mx = max(Mx, ans[to[i]]); //不经过根的
for (int i=head[u]; i; i=nxt[i])
if (to[i] != son[u]) Calc(to[i]), update(to[i]); // update(u) !!! 先更新答案,在更新f数组,(防止计算到在子树内部的路径)
add(u); upd(u);
ans[u] = Mx;
if (!c) Clear(u), Mx = ;
} int main() {
int n = read();
char c[];
for (int i=; i<=n; ++i) {
int u = read(); scanf("%s", c);
add_edge(u, i, c[] - 'a');
}
dfs();
solve(, );
for (int i=; i<=n; ++i) printf("%d ",ans[i]);
return ;
}

CF 741 D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths的更多相关文章

  1. 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,求每个子树中最长的边,满 ...

  2. 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 思路: 树上启发式合并 从根节点出发到每个位置的每个字符的奇偶性记为每个位 ...

  3. 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的 ...

  4. 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 ...

  5. 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 题意 给出一棵树,每条边上有一个字符,字符集大小只 ...

  6. 【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 [题解]这 ...

  7. CF741 D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

    题目意思很清楚了吧,那么我们从重排回文串的性质入手. 很容易得出,只要所有字符出现的次数都为偶数,或者有且只有一个字符出现为奇数就满足要求了. 然后想到什么,Hash?大可不必,可以发现字符\(\in ...

  8. [Codeforces741D]Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths——dsu on tree

    题目链接: Codeforces741D 题目大意:给出一棵树,根为$1$,每条边有一个$a-v$的小写字母,求每个点子树中的一条最长的简单路径使得这条路径上的边上的字母重排后是一个回文串. 显然如果 ...

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

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

随机推荐

  1. hdu5194 DZY Loves Balls 【概率论 or 搜索】

    //yy:那天考完概率论,上网无聊搜个期望可加性就搜到这题,看到以后特别有亲和感,挺有意思的. hdu5194 DZY Loves Balls [概率论 or 搜索] 题意: 一个盒子里有n个黑球和m ...

  2. 阅读MySQL文档第21章摘抄

    触发程序是与表相关的数据库对象. mysql> CREATE TABLE account (acct_num INT, amount DECIMAL(10,2)); Query OK, 0 ro ...

  3. JavaScript 初学备忘录

    JavaScript 是脚本语言 JavaScript 是一种轻量级的编程语言. JavaScript 是可插入 HTML 页面的编程代码. JavaScript 插入 HTML 页面后,可由所有的现 ...

  4. Yii: 扩展CGridView增加导出CSV功能

    Yii提供的CGridView组件没有内置数据导出功能,不过我们可以通过扩展该组件来添加该功能. 具体方法如下: 1.首先派生一个子类,添加一个action成员,在该视图的init函数中判断是浏览动作 ...

  5. oracle数据库恢复归档脚本

    cat restorearch1.sh rman target / << EOFRUN {SET ARCHIVELOG DESTINATION TO '/archlog1/db2_arch ...

  6. TCP/IP模型 & 5层参考模型

    OSl参考模型与TCP/IP参考模型相同点: 1.都分层 2.基于独立的协议栈的概念 3.可以实现异构网络互联

  7. 为什么 window.location.search 为空?

    1,什么是window.location?示例 URL:http://b.a.com:88/index.php?name=kang&when=2011#first 属性 含义 值 protoc ...

  8. supervisord的配置

    https://blog.csdn.net/xyang81/article/details/51555473  这位大佬写的很详细  你们可以去参考一下

  9. x+=i和x = x+i比较 -- 简单赋值和复合赋值

    这两个赋值方式其实是有区别的,如果最后结果的类型和左操作数的类型一样,那么这两个表达式就完全等价. 下面来看看两个例子来理解它们的区别: 编写一个程序,使得x+=i合法, x = x+i: 不合法. ...

  10. 【MongoDB】CentOS上安装MongoDB

    权限部分尚未测试完成,请勿参考. 1.去官方网站下载Mongodb for linux的包,我没找到CentOS的,随便下载了个mongodb-linux-x86_64-amazon-3.2.0.tg ...