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 "
"
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;
}
原文地址:https://www.cnblogs.com/wuyuanyuan/p/9265181.html