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
题意
给出一棵树,每条边上有一个字符,字符集大小只有22。
对于每一个子树,询问其中最长的,满足:路径上的字符集可以重组成字符串的路径的长度。
题解
明显是用mask维护信息,然后启发式合并一下。
一般启发式合并需要用map维护信息,这样的复杂度是log^2的。如果保留每个点重儿子的信息,就可以用全局变量维护,全局变量的大小就可以开很大,可以做到log。
代码
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define rep(i, a, b) for(int i=(a); i<(b); i++)
#define sz(a) (int)a.size()
#define de(a) cout << #a << " = " << a << endl
#define dd(a) cout << #a << " = " << a << " "
#define all(a) a.begin(), a.end()
#define endl "\n"
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
//---
const int N = 505050;
int n;
int ans[N], s[N], par[N], dep[N], wson[N], sz[N], mask[22], len[1<<22];
vi g[N];
vector<pii> info[N];
inline void join(vector<pii> &a, vector<pii> &b, const int &t, const int &c, int &ans) {
if(t) swap(a, b);
for(auto u : b) {
if(~len[u.fi]) ans = max(ans, len[u.fi] + u.se - c);
rep(i, 0, 22) if(~len[u.fi ^ mask[i]]) {
ans = max(ans, len[u.fi ^ mask[i]] + u.se - c);
}
}
for(auto u : b) {
len[u.fi] = max(len[u.fi], u.se);
}
a.insert(a.end(), all(b));
}
void dfs(int u, bool isw) {
info[u].pb(mp(s[u], dep[u]));
if(sz(g[u])) {
for(auto v : g[u]) if(v != wson[u]) {
dfs(v, 0);
ans[u] = max(ans[u], ans[v]);
}
dfs(wson[u], 1);
ans[u] = max(ans[u], ans[wson[u]]);
join(info[u], info[wson[u]], 1, dep[u] * 2, ans[u]);
for(auto v : g[u]) if(v != wson[u]) {
join(info[u], info[v], 0, dep[u] * 2, ans[u]);
}
if(!isw) for(auto t : info[u]) len[t.fi] = -1;
} else {
if(isw) len[s[u]] = max(len[s[u]], dep[u]);
}
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
rep(i, 0, 22) mask[i] = (1 << i);
cin >> n;
rep(i, 2, n+1) {
string t;
cin >> par[i] >> t;
int c = t[0] - 'a';
g[par[i]].pb(i);
s[i] = s[par[i]] ^ mask[c];
dep[i] = dep[par[i]] + 1;
}
for(int i = n; i; --i) {
sz[par[i]] += ++sz[i];
if(sz[wson[par[i]]] < sz[i]) wson[par[i]] = i;
}
memset(len, -1, sizeof(len));
dfs(1, 1);
rep(i, 1, n+1) cout << ans[i] << " ";
cout << endl;
return 0;
}
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
题目链接: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(dsu on tree)
感觉dsu on tree一定程度上还是与点分类似的.考虑求出跨过每个点的最长满足要求的路径,再对子树内取max即可. 重排后可以变成回文串相当于出现奇数次的字母不超过1个.考虑dsu on tree ...
- Codeforces.741D.Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree 思路)
题目链接 \(Description\) 给定一棵树,每条边上有一个字符(a~v).对每个节点,求它的子树中一条最长的路径,满足 路径上所有边上的字符可以重新排列成一个回文串.输出其最长长度. \(n ...
- 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 思路: 树上启发式合并 从根节点出发到每个位置的每个字符的奇偶性记为每个位 ...
- 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 ...
- codeforces 1065F Up and Down the Tree
题目链接:codeforces 1065F Up and Down the Tree 题意:给出一棵树的节点数\(n\)以及一次移动的最大距离\(k\),现在有一个标记在根节点1处,每一次可以进行一下 ...
- 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 600E. Lomsat gelral(Dsu on tree学习)
题目链接:http://codeforces.com/problemset/problem/600/E n个点的有根树,以1为根,每个点有一种颜色.我们称一种颜色占领了一个子树当且仅当没有其他颜色在这 ...
随机推荐
- springboot jpa 多条件查询(多表)
前几天写的,贴上来. 实体类. package com.syl.demo.daomain; import lombok.Data; import javax.persistence.*; /** * ...
- composer windows安装
一.下载安装包安装 https://getcomposer.org/download/(由于墙的限制,可能下载可执行文件失败,即使成功,由于网络的原因,安装的时候也可能会失败,所以建议用第二种方法) ...
- linux中echo命令详解
linux的echo命令, 在shell编程中极为常用, 在终端下打印变量value的时候也是常常用到的, 因此有必要了解下echo的用法 echo命令的功能是在显示器上显示一段文字,一般起到一个提示 ...
- angularjs 从外部改变controller内的数据
var appElement = document.querySelector('[ng-controller=seatsCtrl]'); var $scope = angular.element(a ...
- JQuery判断浏览器类型(IE, Firefox…)
1 2 3 4 5 6 7 8 9 10 11 $(function() { if ($.browser.msie) { alert("这是一个IE浏览器&q ...
- 使用C#利用cmd来调用java jar包获取其中的数据
其实也很简单,就是在C#中构建一个Process,启动jar包,并且给jar包传递参数 因为我并没有怎么学过JAVA,所以只写了个很小的Demo,就是根据传入的参数获取对应的数据 以下是JAVA De ...
- 比较json和fastjson的put()
首先,分别运行下面两段json和fastjson的代码: import org.json.JSONException; import org.json.JSONObject; public class ...
- 微信开发e.target.dataset取值undefined
替换为: e.currentTarget.dataset.current
- Yii 时间戳格式化显示的问题
这个控件是CJuiDatePicker控件的扩展,支持时分秒. 下载地址:http://www.yiiframework.com/extension/timepicker/ 这个控件用在view里的_ ...
- BZOJ1911: [Apio2010]特别行动队(dp 斜率优化)
题意 题目链接 Sol 裸的斜率优化,注意推导过程中的符号问题. #include<bits/stdc++.h> #define Pair pair<int, int> #de ...