【cf741】D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree)
题意:
给出一颗以\(1\)为根的有根树,树边带有一个字符(\(a\)~\(v\))的信息。
输出对于每个结点,其子树内最长的简单路径并且满足边上的字符能够组成回文串。
思路:
- 显然最终的答案分为两部分,子树内部的答案,经过当前根结点的答案。
- 第一种答案很好处理。类似于点分治,主要处理第二种答案。
- 树上路径可以考虑找到\(lca\),维护点到根节点的信息。
- 题目中的回文串可以等价于,出现奇数次的字符不超过\(1\)个。我们将字符状压一下,那么维护点到根的信息就很方便了;同理求出两点间的信息也很方便。
- 因为要枚举两条链中的结点,我们可以类似于树\(dp\)那样,保留之前的信息,然后枚举这条链更新答案并且更新信息。
- 这里显然枚举时枚举轻边最优(类似于启发式合并),那么可以采用\(dsu\ on\ tree\),算法会保留重儿子的信息,我们直接暴力轻儿子即可。
根据\(dsu\ on\ tree\)算法的思想,每个结点只会被暴力到\(O(logn)\)次,所以算法的时间复杂度为\(O(nlogn)\)。
感觉挺考察对\(dsu\ on\ tree\)的理解的。。细节见代码吧:
/*
* Author: heyuhhh
* Created Time: 2019/11/15 16:10:20
*/
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '\n'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
#define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 5e5 + 5;
int n;
char s[N];
vector <int> g[N];
int dis[N], sz[N], bson[N], d[N];
int f[1 << 22];
int ans[N];
void dfs(int u, int fa) {
sz[u] = 1;
int mx = 0;
d[u] = d[fa] + 1;
if(fa) dis[u] = (dis[fa] ^ (1 << (s[u] - 'a')));
for(auto v : g[u]) {
dfs(v, u);
sz[u] += sz[v];
if(sz[v] > mx) {
mx = sz[v]; bson[u] = v;
}
}
}
int Max, D;
void upd(int u) {
if(f[dis[u]]) Max = max(Max, f[dis[u]] + d[u] - D);
for(int i = 0; i < 22; i++) if(f[dis[u] ^ (1 << i)]) {
Max = max(Max, f[dis[u] ^ (1 << i)] + d[u] - D);
}
}
void upd2(int u) {
f[dis[u]] = max(f[dis[u]], d[u]);
}
void go(int u) {
upd(u);
for(auto v : g[u]) go(v);
}
void go2(int u) {
upd2(u);
for(auto v : g[u]) go2(v);
}
void clear(int u) {
f[dis[u]] = 0;
for(auto v : g[u]) clear(v);
}
void dfs2(int u, int fa, int op) {
for(auto v : g[u]) if(v != bson[u]) dfs2(v, u, 0);
if(bson[u]) dfs2(bson[u], u, 1);
for(auto v : g[u]) Max = max(Max, ans[v]);
D = 2 * d[u];
for(auto v : g[u]) if(v != bson[u]) {
go(v); go2(v);
}
upd(u); upd2(u);
ans[u] = Max;
if(!op) {
clear(u), Max = 0;
}
}
void run(){
for(int i = 2; i <= n; i++) {
int p;
scanf("%d %c", &p, &s[i]);
g[p].push_back(i);
}
dfs(1, 0);
dfs2(1, 0, 1);
for(int i = 1; i <= n; i++) cout << ans[i] << " \n"[i == n];
}
int main() {
while(cin >> n) run();
return 0;
}
【cf741】D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree)的更多相关文章
- 【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 [题解]这 ...
- 【iOS】7.4 定位服务->2.1.2 定位 - 官方框架CoreLocation: CLLocationManager(位置管理器)
本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正. 本文相关目录: ================== 所属文集:[iOS]07 设备工具 === ...
- 【CF741D】Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree)
题意:我们称一个字符串为周驿东串当且仅当重排它的字符可以组成一个回文串. 给出一个n个点的有根树,根为1,每条边上有一个从a到v的字符,求每个点的子树中所有简单路径可以组成的周驿东串中的最长长度. n ...
- 【Telerik】实现列表单元格中添加复选框,进行状态(是、否)判断
前台界面: 需求:实现对每条细则是否必备进行判断,必备就勾选,否则不勾选. 首先:要保证列表GridView是可编辑的(IsReadOnly=false) 表格代码 其次:单元格的数据绑定要保证是双向 ...
- 【K8S】基于Docker+K8S+GitLab/SVN+Jenkins+Harbor搭建持续集成交付环境(环境搭建篇)
写在前面 最近在 K8S 1.18.2 版本的集群上搭建DevOps环境,期间遇到了各种坑.目前,搭建环境的过程中出现的各种坑均已被填平,特此记录,并分享给大家! 服务器规划 IP 主机名 节点 操作 ...
- Codeforces 741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree)
感觉dsu on tree一定程度上还是与点分类似的.考虑求出跨过每个点的最长满足要求的路径,再对子树内取max即可. 重排后可以变成回文串相当于出现奇数次的字母不超过1个.考虑dsu on tree ...
- CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree)
一棵根为1 的树,每条边上有一个字符(a-v共22种). 一条简单路径被称为Dokhtar-kosh当且仅当路径上的字符经过重新排序后可以变成一个回文串. 求每个子树中最长的Dokhtar-kosh路 ...
- 【翻译】Anatomy of a Program in Memory—剖析内存中的一个程序(进程的虚拟存储器映像布局详解)
[翻译]Anatomy of a Program in Memory—剖析内存中的一个程序(进程的虚拟存储器映像布局详解) . . .
- 【原创】构建高性能ASP.NET站点 第五章—性能调优综述(后篇)
原文:[原创]构建高性能ASP.NET站点 第五章-性能调优综述(后篇) 构建高性能ASP.NET站点 第五章—性能调优综述(后篇) 前言:本篇主要讲述如何根据一些简单的工具和简单的现象来粗布的定位站 ...
随机推荐
- Script - 检查当前的undo配置和建议设置 (Doc ID 1579035.1)
Script - Check Current Undo Configuration and Advise Recommended Setup (Doc ID 1579035.1) APPLIES TO ...
- Scrapy安装和简单使用
模块安装 Windows 安装scrapy 需要安装依赖环境twisted,twisted又需要安装C++的依赖环境 pip install scrapy 时 如果出现twisted错误 在http ...
- TensorFlow从1到2(十三)图片风格迁移
风格迁移 <从锅炉工到AI专家(8)>中我们介绍了一个"图片风格迁移"的例子.因为所引用的作品中使用了TensorFlow 1.x的代码,算法也相对复杂,所以文中没有仔 ...
- MVC(基础二)
原文链接:https://blog.csdn.net/wuzxc520/article/details/77880783 1.网站开发介绍 2.响应流程 3.MVC 介绍 4.文件夹含义
- poj 3069 Saruman's Army 贪心 题解《挑战程序设计竞赛》
地址 http://poj.org/problem?id=3069 题解 题目可以考虑贪心 尽可能的根据题意选择靠右边的点 注意 开始无标记点 寻找左侧第一个没覆盖的点 再来推算既可能靠右的标记点为一 ...
- Java入门之人需要注意的5大步骤
作为最抢手的程序开发言语之一,Java在互联网领域中的方位无需赘言.抢手也带来了高薪和许多的作业时机,对那些预备通过学习Java来改动自己命运的同学来说,需求做好以下作业. 1.考虑一下 学习Java ...
- ubuntu 16.04无法连接网络;双系统无法上网;连接已断开,你现在处于断开状态
先描述一一下我的问题,若和你的一样,请继续往下看. 我是在原有Windows7系统的台式计算机中安装了ubuntu 16.04,所以目前这台计算机是双系统.打开Windows系统时有线网络正常链接.但 ...
- 关于excel中的vlookup就是查找当前列对应的下一列的值的使用
关于excel中的vlookup就是查找当前列对应的下一列的值的使用 vlookup的使用一些说明 vlookup函数一个4个参数解释下 vlookup(查找的值,表格范围,表格范围中第几列的值,0是 ...
- python处理sqlserver数据库的返回数据
上代码: import SqlHelper.MSSQL as MS import pandas as pd if __name__ == '__main__': #连接数据库 ms = MS.MSSQ ...
- 数据库-表操作(CRUD)
1.数据增删改 2.单表查询 3.正则表达式 4.多表查询 笛卡尔积 内连接 外链接 子查询 一.数据的增删改 为什么不说查 因为查询语句 有很多细节 所以先从简单的说起 添加数据: ...